A shared link says what we sell, and names the company behind it - #334
Merged
Conversation
Apolloccrypt
added a commit
that referenced
this pull request
Sep 2, 2026
…does Review of #334 found the head elements were consistent but not honest, and not pinned. Eleven points, all inside <head>. Who is behind it, visible to people The founder and the legal entity were in the JSON-LD only, which no preview in WhatsApp, LinkedIn or iMessage renders. The meta description, og:description and twitter:description of /index and /about now carry the same sentence the footer and /about already print: a product of Paramantis Solutions B.V. in Harderwijk, founded by Mick Beer, privacy and security researcher. Preview text a buyer can read Algorithm names and internal words are out of the sentence a search result shows. /verify no longer opens with ML-DSA-65 (FIPS 204) but with what the page does. The same for /sign, /index, /vault, /download, /pricing, /trust, /audit-log-export, /status, /sla and /co-sign. The word "relay" is ours, not the reader's, so it is out of every title and out of every first sentence except on the four pages whose subject is the architecture itself. The names stay on the pages, where there is room to explain them. A title the page keeps "Sign and send without a US server" was the clearest sentence on the site and appeared nowhere on the page, and it promoted a claim /security contradicts: Cloudflare is on the third-party list there. The title is now "Sign and send documents under EU law", which is what rule 04 on the homepage says and what /security backs. Prices in the pricing description /pricing promised "organisations pay for higher limits" and named no amount. It now names ParaSend Pro at 15 euro a month and ParaSign Pro at 49, excl. VAT, the figures on the page. The first sentence is the free plan, which is the point of the plan structure. The first screen of the page itself is body work and out of scope here. Product names after the verb /index and /pricing opened with ParaSign and ParaSend as if the reader knew them. Both now open with the action. Three gates, because consistency is not truth The gate added earlier pins title, og:title and twitter:title to each other, which the sentence "Paramant is ISO 27001 certified and free forever" passed on all three. Added: - the sentences of /index, /pricing and /about are pinned word for word - no title or description may claim a certification, an accreditation, a qualified signature or a 100% guarantee, none of which the site backs - the title and the first sentence of the description stay free of ML-DSA, ML-KEM, FIPS, .prmnt, AES-n, envelope, open-core and relay, except on /architecture, /crypto-agility, /ct-log and the OT brief Loose ends from the review - the test comment no longer cites docs/brand/messaging.md, which is still an open PR and not in the repo - /parashare is private in both PRIVATE sets, so its head is back to what main has: a gated page should not carry an ungated head change - admin, account and iot carried "PARAMANT" and an em-dash in og and twitter tags; they are private, but the claim that both are gone from every head is now true - merged origin/main, so /parasign from #325 is covered by the new gates Green: seo-contract (14), links, ui-truthfulness, site-claims, navigation-shell, frontend-loading-contract, frontend-module-scripts, pricing-page, the full root integration set (123), check-csp-inline, check-cache-bust, eslint. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XJk2nCLCLmi3F71qkCUn7N
Apolloccrypt
force-pushed
the
feat/fe-meta
branch
2 times, most recently
from
September 2, 2026 17:48
4f8476c to
a82f611
Compare
Apolloccrypt
force-pushed
the
feat/fe-meta
branch
2 times, most recently
from
September 2, 2026 18:05
ca52f4d to
586e9b9
Compare
Apolloccrypt
force-pushed
the
feat/fe-meta
branch
3 times, most recently
from
September 2, 2026 18:11
f2ae7c7 to
e98f122
Compare
Head elements only: title, meta description, Open Graph, Twitter cards and JSON-LD on 50 of the 60 frontend pages. No body text, no styling. apply-nav.py and js/nav-auth.js are untouched, and no diff hunk in any of the 50 files falls after </head>. Rebased on main. Main's wording wins in every head it already writes to the messaging guide (#331): the homepage keeps the title, the description sentence and the SoftwareApplication node #328 gave it, and the Organization description keeps "Dutch company, servers in Germany". This branch adds what main does not have: the founder, the legal entity, the address and the KvK number in the Organization node of every public page, and Open Graph and Twitter cards that match the title. The legal entity is now in the description itself on /, /about and /pricing, not only in the JSON-LD no preview renders. The founder's name is in one description, /about, because that is the only one of the three where /about's own sentence backs it; on / and /pricing the description names Paramantis Solutions B.V. and the founder stays in the Organization node. Jargon is out of the sentence a buyer reads first. /verify says what it gets you instead of naming FIPS 204, and "relay" is gone from every title and every opening sentence except the four pages whose subject is the architecture. /sign says "the document text and your signing key never leave it", not "the file". In Request signatures the encrypted document does go to Paramant, which is how a recipient receives it. The plaintext and the key stay in the browser in all three modes; the file does not. /pricing names a floor per product, sending from 15 euro a month and signing from 49. An unsplit "from 15 euro" reads as if signing starts there. The free plan is called Community in the head as well, on /pricing and /signup. Three gates in tests/seo-contract.test.mjs: - title, og:title, twitter:title and the JSON-LD WebPage name are one sentence. /trust shipped three different names at once and nothing failed. - eight pages have their title and description pinned word for word, with the source of every claim named in the file. - no title or description carries a certification we do not hold, and none carries our own vocabulary. bron-seo/apply_seo_head.py reproduces every generated block exactly: "would change: 0 pages". Main drifted by one page before this commit, because carries that shape instead.
Apolloccrypt
force-pushed
the
feat/fe-meta
branch
from
September 2, 2026 18:13
e98f122 to
cbcb788
Compare
Apolloccrypt
added a commit
that referenced
this pull request
Sep 2, 2026
#334 tightened the head contract: the JSON-LD WebPage name has to be the page title character for character, and every public page has to carry an Organization node naming the company and the founder. /parasend was written before that landed, so on the merged result tests/seo-contract.test.mjs failed twice: the WebPage name used a hyphen where the title uses a middot, and there was no Organization node at all. The block comes from bron-seo/apply_seo_head.py, not from hand editing, so it is the same graph the other 39 pages carry and it stays that way the next time the script runs. `--check` is clean afterwards. Found by rebasing on main and running the suite against the merged tree. A green run on the branch head only describes the branch head, which is how this would have reached main red.
Apolloccrypt
added a commit
that referenced
this pull request
Sep 2, 2026
The three pages a buyer reaches after the homepage were written for someone
who already believes the product. /about opened on the mission and put the
founder in section 03, below the cryptography. /security opened on defence in
depth and kept the one row a buyer came for, the jurisdiction table, seven
screens down. /trust never said who it was for.
They now run the order docs/brand/messaging.md fixes: what this is, who it is
for, who is behind it, a next step, then the proof including the honest
limits. Copy, hierarchy and order only. No restyle. index.html, apply-nav.py
and js/nav-auth.js are untouched.
/about is the founder page.
The lede is plain language: sign and send documents so only you and the
recipient can read them, so anyone can check later that the document is
genuine, on servers in Germany under EU law. Under it, in the first phone
screen, who it is for, then Mick Beer with the title the guide fixes, then
two buttons. Measured at 390x844: the founder sits at y=463 and the second
button at y=608. The section number "00" is hidden in the mobile override
instead of landing under the H1 as a stray number.
Two sentences are gone. "The cryptography is post-quantum, which is the
proof that it still holds up in ten years" was not a proof and not
checkable, on the page whose argument is that everything on it is
checkable. The founder paragraph explained the free plan with a
jurisdiction claim ("should not depend on a US subscription"), which the
guide forbids beside his name. In its place stands the paragraph #332
landed on main while this branch was in review: the Community plan is his
way of giving something back to society, the business plans pay for it,
that is the whole arrangement, and it is why the Community plan is not a
trial and has no end date. Taken from main verbatim, moved with the section
into the top half, and pinned so the two copies cannot drift.
The tier block names the free plan Community, which is what /pricing prints
on the card since #328.
/security answers "why would I trust you" before it answers "how it works".
The promise carries its own scope. It read "even if our own server is
broken into, nobody can read your documents" flat out, while ten screens
lower the page says the Chromium and Outlook extensions take a server-side
encryption path. For an extension user the flat version is untrue today, so
the exception now travels with the promise, in the hero.
It also says what that exception costs the reader, in words rather than in
ours: the extensions encrypt on our server, which means we can read what
you upload through them until that is changed. "Treat those uploads as
relay-side" was the internal phrasing, and relay is exactly the word this
branch removed from the /trust hero. Neither hero uses it now, and a test
says so.
The first screen also carries who is behind the page (Paramantis Solutions
B.V., Harderwijk, KvK 42115132, and the founder line) and the next step.
The buttons used to sit at roughly y=11400 on a phone; "See pricing" is now
at y=656 and "Verify a document" at y=716.
The free plan is Community here too. A first version of this branch left
"ParaSign Free and ParaSend Free cost EUR 0" standing at r.448, because the
only check that forbade the old name was scoped to /about. That check now
covers all three pages, and the sitewide sweep in ui-truthfulness gained the
shape it was missing, so any page using it fails. The page description no
longer sells "relay architecture" either.
The audit block says what /docs#audits actually adds up to: three external
audits in April 2026, two by R. Zwarts and one by Ryan Williams of Smart
Cyber Solutions, forty findings, four of them critical, with the resolving
commits in the table. The previous round claimed "the audit reports
themselves are not published" and pinned it. That was false:
docs/security-audit-2026-04.md is the full Smart Cyber Solutions writeup
and it ships in the site tree. Only the raw pentest output is missing,
which is what that document itself calls the raw report. Both pages now say
that, and link the report.
The CLOUD Act row and the EU-law card move to the data-path wording, as
section 9.2 of the guide requires: no US provider in the data path, with
Resend named as the one exception in the same breath. The old row read "not
applicable: no US infrastructure, no US company", which is broader than
/privacy allows.
/trust names its reader, then gives that reader somewhere to go.
The hero addresses organisations running their own relay and anyone
checking a supplier, and now offers them two buttons instead of one text
link mid-paragraph (y=416 and y=476). The first sentence under the hero no
longer says "the operator who runs the relay": relay is not a word a
supplier reviewer knows.
The page called itself Trust & Verification in its title and H1 while the
social card and the structured data still said Trust & Transparency. #334
then rewrote every head on the site, so the literal strings belong there and
tests/seo-contract.test.mjs pins them. What this branch pins is the
relation: the title, og:title, twitter:title and the JSON-LD name must name
the page the same, and that name must contain the words the H1 uses.
Punctuation and case are not the point; Transparency versus Verification
was. Its plan sentence named two of the three paid
ParaSign tiers; it names all three, and both free tiers as Community.
Tests
tests/ui-truthfulness.test.mjs pins each of the above, and each one was
sabotaged in place to confirm it goes red: the ten-year promise, the
give-back sentence, the US-subscription framing, the Community rename, the
CLOUD Act row, the Resend exception dropped from the card, the finding
counts, the "reports not published" sentence, the auditor names on
/security as well as /trust, the two hero buttons on each page, the
who-is-behind line, the bounded promise, the /trust og:title and JSON-LD
name, the jargon in the first screen, and the paid tiers. Twenty-five
sabotages, twenty-five red, no gaps.
tests/site-claims.test.mjs block 11 reads the numbers out of the /pricing
tier card that owns them and requires /about to repeat them; it follows the
Community rename and now also forbids "ParaSign Free" on /about.
node --test over the CI glob: 162 pass, 0 fail. check-csp-inline,
check-cache-bust and eslint exit 0. At 390px all three pages have
scrollWidth === clientWidth === 390.
Still open, deliberately
The eIDAS level (SES on /about, advanced (AES) in the /pricing FAQ) is a
real contradiction and needs a decision, not a copy edit. This branch stops
it spreading and pins that it stays on the one page that has always carried
it.
This was referenced Sep 2, 2026
Apolloccrypt
added a commit
that referenced
this pull request
Sep 2, 2026
The three pages a buyer reaches after the homepage were written for someone
who already believes the product. /about opened on the mission and put the
founder in section 03, below the cryptography. /security opened on defence in
depth and kept the one row a buyer came for, the jurisdiction table, seven
screens down. /trust never said who it was for.
They now run the order docs/brand/messaging.md fixes: what this is, who it is
for, who is behind it, a next step, then the proof including the honest
limits. Copy, hierarchy and order only. No restyle. index.html, apply-nav.py
and js/nav-auth.js are untouched.
/about is the founder page.
The lede is plain language: sign and send documents so only you and the
recipient can read them, so anyone can check later that the document is
genuine, on servers in Germany under EU law. Under it, in the first phone
screen, who it is for, then Mick Beer with the title the guide fixes, then
two buttons. Measured at 390x844: the founder sits at y=463 and the second
button at y=608. The section number "00" is hidden in the mobile override
instead of landing under the H1 as a stray number.
Two sentences are gone. "The cryptography is post-quantum, which is the
proof that it still holds up in ten years" was not a proof and not
checkable, on the page whose argument is that everything on it is
checkable. The founder paragraph explained the free plan with a
jurisdiction claim ("should not depend on a US subscription"), which the
guide forbids beside his name. In its place stands the paragraph #332
landed on main while this branch was in review: the Community plan is his
way of giving something back to society, the business plans pay for it,
that is the whole arrangement, and it is why the Community plan is not a
trial and has no end date. Taken from main verbatim, moved with the section
into the top half, and pinned so the two copies cannot drift.
The tier block names the free plan Community, which is what /pricing prints
on the card since #328.
/security answers "why would I trust you" before it answers "how it works".
The promise carries its own scope. It read "even if our own server is
broken into, nobody can read your documents" flat out, while ten screens
lower the page says the Chromium and Outlook extensions take a server-side
encryption path. For an extension user the flat version is untrue today, so
the exception now travels with the promise, in the hero.
It also says what that exception costs the reader, in words rather than in
ours: the extensions encrypt on our server, which means we can read what
you upload through them until that is changed. "Treat those uploads as
relay-side" was the internal phrasing, and relay is exactly the word this
branch removed from the /trust hero. Neither hero uses it now, and a test
says so.
The first screen also carries who is behind the page (Paramantis Solutions
B.V., Harderwijk, KvK 42115132, and the founder line) and the next step.
The buttons used to sit at roughly y=11400 on a phone; "See pricing" is now
at y=656 and "Verify a document" at y=716.
The free plan is Community here too. A first version of this branch left
"ParaSign Free and ParaSend Free cost EUR 0" standing at r.448, because the
only check that forbade the old name was scoped to /about. That check now
covers all three pages, and the sitewide sweep in ui-truthfulness gained the
shape it was missing, so any page using it fails. The page description no
longer sells "relay architecture" either.
The audit block says what /docs#audits actually adds up to: three external
audits in April 2026, two by R. Zwarts and one by Ryan Williams of Smart
Cyber Solutions, forty findings, four of them critical, with the resolving
commits in the table. The previous round claimed "the audit reports
themselves are not published" and pinned it. That was false:
docs/security-audit-2026-04.md is the full Smart Cyber Solutions writeup
and it ships in the site tree. Only the raw pentest output is missing,
which is what that document itself calls the raw report. Both pages now say
that, and link the report.
The CLOUD Act row and the EU-law card move to the data-path wording, as
section 9.2 of the guide requires: no US provider in the data path, with
Resend named as the one exception in the same breath. The old row read "not
applicable: no US infrastructure, no US company", which is broader than
/privacy allows.
/trust names its reader, then gives that reader somewhere to go.
The hero addresses organisations running their own relay and anyone
checking a supplier, and now offers them two buttons instead of one text
link mid-paragraph (y=416 and y=476). The first sentence under the hero no
longer says "the operator who runs the relay": relay is not a word a
supplier reviewer knows.
The page called itself Trust & Verification in its title and H1 while the
social card and the structured data still said Trust & Transparency. #334
then rewrote every head on the site, so the literal strings belong there and
tests/seo-contract.test.mjs pins them. What this branch pins is the
relation: the title, og:title, twitter:title and the JSON-LD name must name
the page the same, and that name must contain the words the H1 uses.
Punctuation and case are not the point; Transparency versus Verification
was. Its plan sentence named two of the three paid
ParaSign tiers; it names all three, and both free tiers as Community.
Tests
tests/ui-truthfulness.test.mjs pins each of the above, and each one was
sabotaged in place to confirm it goes red: the ten-year promise, the
give-back sentence, the US-subscription framing, the Community rename, the
CLOUD Act row, the Resend exception dropped from the card, the finding
counts, the "reports not published" sentence, the auditor names on
/security as well as /trust, the two hero buttons on each page, the
who-is-behind line, the bounded promise, the /trust og:title and JSON-LD
name, the jargon in the first screen, and the paid tiers. Twenty-six
sabotages, twenty-six red, no gaps.
tests/site-claims.test.mjs block 11 reads the numbers out of the /pricing
tier card that owns them and requires /about to repeat them; it follows the
Community rename and now also forbids "ParaSign Free" on /about.
node --test over the CI glob: 162 pass, 0 fail. check-csp-inline,
check-cache-bust and eslint exit 0. At 390px all three pages have
scrollWidth === clientWidth === 390.
Two things this branch had to touch on main's side
tests/ui-truthfulness.test.mjs did not parse on main: #336 and #339 each
landed a const named pricingVisible in the same module, for two different
values. The one #339 added is renamed to pricingText, with a comment saying
why. Without it nothing in this file runs, this branch included.
tests/site-claims.test.mjs block 12 read the /pricing tier cards by their
section heading. #336 renamed both headings and put ParaSign first, so the
split now finds them by product prefix and orders them by position.
Not touched, and still broken on main: relay/test/pricing-page.test.js r.498
declares tiers twice, so eslint cannot parse it. It is outside these three
pages and outside this PR.
Still open, deliberately
The eIDAS level (SES on /about, advanced (AES) in the /pricing FAQ) is a
real contradiction and needs a decision, not a copy edit. This branch stops
it spreading and pins that it stays on the one page that has always carried
it.
Apolloccrypt
added a commit
that referenced
this pull request
Sep 2, 2026
The three pages a buyer reaches after the homepage were written for someone
who already believes the product. /about opened on the mission and put the
founder in section 03, below the cryptography. /security opened on defence in
depth and kept the one row a buyer came for, the jurisdiction table, seven
screens down. /trust never said who it was for.
They now run the order docs/brand/messaging.md fixes: what this is, who it is
for, who is behind it, a next step, then the proof including the honest
limits. Copy, hierarchy and order only. No restyle. index.html, apply-nav.py
and js/nav-auth.js are untouched.
/about is the founder page.
The lede is plain language: sign and send documents so only you and the
recipient can read them, so anyone can check later that the document is
genuine, on servers in Germany under EU law. Under it, in the first phone
screen, who it is for, then Mick Beer with the title the guide fixes, then
two buttons. Measured at 390x844: the founder sits at y=463 and the second
button at y=608. The section number "00" is hidden in the mobile override
instead of landing under the H1 as a stray number.
Two sentences are gone. "The cryptography is post-quantum, which is the
proof that it still holds up in ten years" was not a proof and not
checkable, on the page whose argument is that everything on it is
checkable. The founder paragraph explained the free plan with a
jurisdiction claim ("should not depend on a US subscription"), which the
guide forbids beside his name. In its place stands the paragraph #332
landed on main while this branch was in review: the Community plan is his
way of giving something back to society, the business plans pay for it,
that is the whole arrangement, and it is why the Community plan is not a
trial and has no end date. Taken from main verbatim, moved with the section
into the top half, and pinned so the two copies cannot drift.
The tier block names the free plan Community, which is what /pricing prints
on the card since #328.
/security answers "why would I trust you" before it answers "how it works".
The promise carries its own scope. It read "even if our own server is
broken into, nobody can read your documents" flat out, while ten screens
lower the page says the Chromium and Outlook extensions take a server-side
encryption path. For an extension user the flat version is untrue today, so
the exception now travels with the promise, in the hero.
It also says what that exception costs the reader, in words rather than in
ours: the extensions encrypt on our server, which means we can read what
you upload through them until that is changed. "Treat those uploads as
relay-side" was the internal phrasing, and relay is exactly the word this
branch removed from the /trust hero. Neither hero uses it now, and a test
says so.
The first screen also carries who is behind the page (Paramantis Solutions
B.V., Harderwijk, KvK 42115132, and the founder line) and the next step.
The buttons used to sit at roughly y=11400 on a phone; "See pricing" is now
at y=656 and "Verify a document" at y=716.
The free plan is Community here too. A first version of this branch left
"ParaSign Free and ParaSend Free cost EUR 0" standing at r.448, because the
only check that forbade the old name was scoped to /about. That check now
covers all three pages, and the sitewide sweep in ui-truthfulness gained the
shape it was missing, so any page using it fails. The page description no
longer sells "relay architecture" either.
The audit block says what /docs#audits actually adds up to: three external
audits in April 2026, two by R. Zwarts and one by Ryan Williams of Smart
Cyber Solutions, forty findings, four of them critical, with the resolving
commits in the table. The previous round claimed "the audit reports
themselves are not published" and pinned it. That was false:
docs/security-audit-2026-04.md is the full Smart Cyber Solutions writeup
and it ships in the site tree. Only the raw pentest output is missing,
which is what that document itself calls the raw report. Both pages now say
that, and link the report.
The CLOUD Act row and the EU-law card move to the data-path wording, as
section 9.2 of the guide requires: no US provider in the data path, with
Resend named as the one exception in the same breath. The old row read "not
applicable: no US infrastructure, no US company", which is broader than
/privacy allows.
/trust names its reader, then gives that reader somewhere to go.
The hero addresses organisations running their own relay and anyone
checking a supplier, and now offers them two buttons instead of one text
link mid-paragraph (y=416 and y=476). The first sentence under the hero no
longer says "the operator who runs the relay": relay is not a word a
supplier reviewer knows.
The page called itself Trust & Verification in its title and H1 while the
social card and the structured data still said Trust & Transparency. #334
then rewrote every head on the site, so the literal strings belong there and
tests/seo-contract.test.mjs pins them. What this branch pins is the
relation: the title, og:title, twitter:title and the JSON-LD name must name
the page the same, and that name must contain the words the H1 uses.
Punctuation and case are not the point; Transparency versus Verification
was. Its plan sentence named two of the three paid
ParaSign tiers; it names all three, and both free tiers as Community.
Tests
tests/ui-truthfulness.test.mjs pins each of the above, and each one was
sabotaged in place to confirm it goes red: the ten-year promise, the
give-back sentence, the US-subscription framing, the Community rename, the
CLOUD Act row, the Resend exception dropped from the card, the finding
counts, the "reports not published" sentence, the auditor names on
/security as well as /trust, the two hero buttons on each page, the
who-is-behind line, the bounded promise, the /trust og:title and JSON-LD
name, the jargon in the first screen, and the paid tiers. Twenty-six
sabotages, twenty-six red, no gaps.
tests/site-claims.test.mjs block 11 reads the numbers out of the /pricing
tier card that owns them and requires /about to repeat them; it follows the
Community rename and now also forbids "ParaSign Free" on /about.
node --test over the CI glob: 162 pass, 0 fail. check-csp-inline,
check-cache-bust and eslint exit 0. At 390px all three pages have
scrollWidth === clientWidth === 390.
Three things this branch had to touch on main's side
tests/ui-truthfulness.test.mjs did not parse on main: #336 and #339 each
landed a const named pricingVisible in the same module, for two different
values. The one #339 added is renamed to pricingText, with a comment saying
why. Without it nothing in this file runs, this branch included.
tests/site-claims.test.mjs block 12 read the /pricing tier cards by their
section heading. #336 renamed both headings and put ParaSign first, so the
split now finds them by product prefix and orders them by position.
relay/test/pricing-page.test.js r.498 required ../lib/tiers a second time,
under a name the file already binds at r.18. That is a SyntaxError, and it
took down two CI checks on every PR: "static, every name must exist" (eslint
cannot parse the file) and "relay - unit suite". The duplicate line is
removed; the binding at the top of the file is the same module. This was
outside the three pages, but no PR can go green while it stands.
Still open, deliberately
The eIDAS level (SES on /about, advanced (AES) in the /pricing FAQ) is a
real contradiction and needs a decision, not a copy edit. This branch stops
it spreading and pins that it stays on the one page that has always carried
it.
Apolloccrypt
added a commit
that referenced
this pull request
Sep 2, 2026
The three pages a buyer reaches after the homepage were written for someone
who already believes the product. /about opened on the mission and put the
founder in section 03, below the cryptography. /security opened on defence in
depth and kept the one row a buyer came for, the jurisdiction table, seven
screens down. /trust never said who it was for.
They now run the order docs/brand/messaging.md fixes: what this is, who it is
for, who is behind it, a next step, then the proof including the honest
limits. Copy, hierarchy and order only. No restyle. index.html, apply-nav.py
and js/nav-auth.js are untouched.
/about is the founder page.
The lede is plain language: sign and send documents so only you and the
recipient can read them, so anyone can check later that the document is
genuine, on servers in Germany under EU law. Under it, in the first phone
screen, who it is for, then Mick Beer with the title the guide fixes, then
two buttons. Measured at 390x844: the founder sits at y=463 and the second
button at y=608. The section number "00" is hidden in the mobile override
instead of landing under the H1 as a stray number.
Two sentences are gone. "The cryptography is post-quantum, which is the
proof that it still holds up in ten years" was not a proof and not
checkable, on the page whose argument is that everything on it is
checkable. The founder paragraph explained the free plan with a
jurisdiction claim ("should not depend on a US subscription"), which the
guide forbids beside his name. In its place stands the paragraph #332
landed on main while this branch was in review: the Community plan is his
way of giving something back to society, the business plans pay for it,
that is the whole arrangement, and it is why the Community plan is not a
trial and has no end date. Taken from main verbatim, moved with the section
into the top half, and pinned so the two copies cannot drift.
The tier block names the free plan Community, which is what /pricing prints
on the card since #328.
/security answers "why would I trust you" before it answers "how it works".
The promise carries its own scope. It read "even if our own server is
broken into, nobody can read your documents" flat out, while ten screens
lower the page says the Chromium and Outlook extensions take a server-side
encryption path. For an extension user the flat version is untrue today, so
the exception now travels with the promise, in the hero.
It also says what that exception costs the reader, in words rather than in
ours: the extensions encrypt on our server, which means we can read what
you upload through them until that is changed. "Treat those uploads as
relay-side" was the internal phrasing, and relay is exactly the word this
branch removed from the /trust hero. Neither hero uses it now, and a test
says so.
The first screen also carries who is behind the page (Paramantis Solutions
B.V., Harderwijk, KvK 42115132, and the founder line) and the next step.
The buttons used to sit at roughly y=11400 on a phone; "See pricing" is now
at y=656 and "Verify a document" at y=716.
The free plan is Community here too. A first version of this branch left
"ParaSign Free and ParaSend Free cost EUR 0" standing at r.448, because the
only check that forbade the old name was scoped to /about. That check now
covers all three pages, and the sitewide sweep in ui-truthfulness gained the
shape it was missing, so any page using it fails. The page description no
longer sells "relay architecture" either.
The audit block says what /docs#audits actually adds up to: three external
audits in April 2026, two by R. Zwarts and one by Ryan Williams of Smart
Cyber Solutions, forty findings, four of them critical, with the resolving
commits in the table. The previous round claimed "the audit reports
themselves are not published" and pinned it. That was false:
docs/security-audit-2026-04.md is the full Smart Cyber Solutions writeup
and it ships in the site tree. Only the raw pentest output is missing,
which is what that document itself calls the raw report. Both pages now say
that, and link the report.
The CLOUD Act row and the EU-law card move to the data-path wording, as
section 9.2 of the guide requires: no US provider in the data path, with
Resend named as the one exception in the same breath. The old row read "not
applicable: no US infrastructure, no US company", which is broader than
/privacy allows.
/trust names its reader, then gives that reader somewhere to go.
The hero addresses organisations running their own relay and anyone
checking a supplier, and now offers them two buttons instead of one text
link mid-paragraph (y=416 and y=476). The first sentence under the hero no
longer says "the operator who runs the relay": relay is not a word a
supplier reviewer knows.
The page called itself Trust & Verification in its title and H1 while the
social card and the structured data still said Trust & Transparency. #334
then rewrote every head on the site, so the literal strings belong there and
tests/seo-contract.test.mjs pins them. What this branch pins is the
relation: the title, og:title, twitter:title and the JSON-LD name must name
the page the same, and that name must contain the words the H1 uses.
Punctuation and case are not the point; Transparency versus Verification
was. Its plan sentence named two of the three paid
ParaSign tiers; it names all three, and both free tiers as Community.
Tests
tests/ui-truthfulness.test.mjs pins each of the above, and each one was
sabotaged in place to confirm it goes red: the ten-year promise, the
give-back sentence, the US-subscription framing, the Community rename, the
CLOUD Act row, the Resend exception dropped from the card, the finding
counts, the "reports not published" sentence, the auditor names on
/security as well as /trust, the two hero buttons on each page, the
who-is-behind line, the bounded promise, the /trust og:title and JSON-LD
name, the jargon in the first screen, and the paid tiers. Twenty-seven
sabotages, twenty-seven red, no gaps.
tests/site-claims.test.mjs block 11 reads the numbers out of the /pricing
tier card that owns them and requires /about to repeat them; it follows the
Community rename and now also forbids "ParaSign Free" on /about.
node --test over the CI glob: 173 pass, 0 fail. check-csp-inline,
check-cache-bust and eslint exit 0, bron-seo/apply_seo_head.py --check
reports 0 pages, and tests/static-sanity.sh is PASS on all eleven checks,
including #362's new test-scope guard. At 390px all three pages have
scrollWidth === clientWidth === 390.
Following main through four parallel merges
#359 landed the deduplication this branch was carrying (the second const
tiers in relay/test/pricing-page.test.js, and pricingVisible renamed to
pricingText), so both local fixes are dropped in favour of main's.
This branch's own block in tests/ui-truthfulness.test.mjs now sits inside a
bare block scope and declares nothing at module level. Four PRs merged into
that file in parallel on 2 September and two of them collided on a top-level
const, which is a SyntaxError: not one assertion in the file runs, on any
branch. A block that declares nothing at module level cannot do that to the
next branch.
tests/site-claims.test.mjs block 12 stopped spelling the units itself. #336
renamed both /pricing section headings and put ParaSign first, and #359
reworded "2 signatures per month" to "2 signatures a month". The block now
finds the headings by product prefix, orders them by position, and lifts each
fact out of the card as a whole phrase, so /about repeats what /pricing says
rather than what this file guesses /pricing says. /about follows the new
wording: "2 signatures a month", "24 hour link expiry", "up to 10 reads per
link".
Still open, deliberately
The eIDAS level (SES on /about, advanced (AES) in the /pricing FAQ) is a
real contradiction and needs a decision, not a copy edit. This branch stops
it spreading and pins that it stays on the one page that has always carried
it.
Apolloccrypt
added a commit
that referenced
this pull request
Sep 2, 2026
The three pages a buyer reaches after the homepage were written for someone
who already believes the product. /about opened on the mission and put the
founder in section 03, below the cryptography. /security opened on defence in
depth and kept the one row a buyer came for, the jurisdiction table, seven
screens down. /trust never said who it was for.
They now run the order docs/brand/messaging.md fixes: what this is, who it is
for, who is behind it, a next step, then the proof including the honest
limits. Copy, hierarchy and order only. No restyle. index.html, apply-nav.py
and js/nav-auth.js are untouched.
/about is the founder page.
The lede is plain language: sign and send documents so only you and the
recipient can read them, so anyone can check later that the document is
genuine, on servers in Germany under EU law. Under it, in the first phone
screen, who it is for, then Mick Beer with the title the guide fixes, then
two buttons. Measured at 390x844: the founder sits at y=463 and the second
button at y=608. The section number "00" is hidden in the mobile override
instead of landing under the H1 as a stray number.
Two sentences are gone. "The cryptography is post-quantum, which is the
proof that it still holds up in ten years" was not a proof and not
checkable, on the page whose argument is that everything on it is
checkable. The founder paragraph explained the free plan with a
jurisdiction claim ("should not depend on a US subscription"), which the
guide forbids beside his name. In its place stands the paragraph #332
landed on main while this branch was in review: the Community plan is his
way of giving something back to society, the business plans pay for it,
that is the whole arrangement, and it is why the Community plan is not a
trial and has no end date. Taken from main verbatim, moved with the section
into the top half, and pinned so the two copies cannot drift.
The tier block names the free plan Community, which is what /pricing prints
on the card since #328.
/security answers "why would I trust you" before it answers "how it works".
The promise carries its own scope. It read "even if our own server is
broken into, nobody can read your documents" flat out, while ten screens
lower the page says the Chromium and Outlook extensions take a server-side
encryption path. For an extension user the flat version is untrue today, so
the exception now travels with the promise, in the hero.
It also says what that exception costs the reader, in words rather than in
ours: the extensions encrypt on our server, which means we can read what
you upload through them until that is changed. "Treat those uploads as
relay-side" was the internal phrasing, and relay is exactly the word this
branch removed from the /trust hero. Neither hero uses it now, and a test
says so.
The first screen also carries who is behind the page (Paramantis Solutions
B.V., Harderwijk, KvK 42115132, and the founder line) and the next step.
The buttons used to sit at roughly y=11400 on a phone; "See pricing" is now
at y=656 and "Verify a document" at y=716.
The free plan is Community here too. A first version of this branch left
"ParaSign Free and ParaSend Free cost EUR 0" standing at r.448, because the
only check that forbade the old name was scoped to /about. That check now
covers all three pages, and the sitewide sweep in ui-truthfulness gained the
shape it was missing, so any page using it fails. The page description no
longer sells "relay architecture" either.
The audit block says what /docs#audits actually adds up to: three external
audits in April 2026, two by R. Zwarts and one by Ryan Williams of Smart
Cyber Solutions, forty findings, four of them critical, with the resolving
commits in the table. The previous round claimed "the audit reports
themselves are not published" and pinned it. That was false:
docs/security-audit-2026-04.md is the full Smart Cyber Solutions writeup
and it ships in the site tree. Only the raw pentest output is missing,
which is what that document itself calls the raw report. Both pages now say
that, and link the report.
The CLOUD Act row and the EU-law card move to the data-path wording, as
section 9.2 of the guide requires: no US provider in the data path, with
Resend named as the one exception in the same breath. The old row read "not
applicable: no US infrastructure, no US company", which is broader than
/privacy allows.
/trust names its reader, then gives that reader somewhere to go.
The hero addresses organisations running their own relay and anyone
checking a supplier, and now offers them two buttons instead of one text
link mid-paragraph (y=416 and y=476). The first sentence under the hero no
longer says "the operator who runs the relay": relay is not a word a
supplier reviewer knows.
The page called itself Trust & Verification in its title and H1 while the
social card and the structured data still said Trust & Transparency. #334
then rewrote every head on the site, so the literal strings belong there and
tests/seo-contract.test.mjs pins them. What this branch pins is the
relation: the title, og:title, twitter:title and the JSON-LD name must name
the page the same, and that name must contain the words the H1 uses.
Punctuation and case are not the point; Transparency versus Verification
was. Its plan sentence named two of the three paid
ParaSign tiers; it names all three, and both free tiers as Community.
Tests
tests/ui-truthfulness.test.mjs pins each of the above, and each one was
sabotaged in place to confirm it goes red: the ten-year promise, the
give-back sentence, the US-subscription framing, the Community rename, the
CLOUD Act row, the Resend exception dropped from the card, the finding
counts, the "reports not published" sentence, the auditor names on
/security as well as /trust, the two hero buttons on each page, the
who-is-behind line, the bounded promise, the /trust og:title and JSON-LD
name, the jargon in the first screen, and the paid tiers. Twenty-seven
sabotages, twenty-seven red, no gaps.
tests/site-claims.test.mjs block 11 reads the numbers out of the /pricing
tier card that owns them and requires /about to repeat them; it follows the
Community rename and now also forbids "ParaSign Free" on /about.
node --test over the CI glob: 173 pass, 0 fail. check-csp-inline,
check-cache-bust and eslint exit 0, bron-seo/apply_seo_head.py --check
reports 0 pages, and tests/static-sanity.sh is PASS on all eleven checks,
including #362's new test-scope guard. At 390px all three pages have
scrollWidth === clientWidth === 390.
Following main through four parallel merges
#359 landed the deduplication this branch was carrying (the second const
tiers in relay/test/pricing-page.test.js, and pricingVisible renamed to
pricingText), so both local fixes are dropped in favour of main's.
This branch's own block in tests/ui-truthfulness.test.mjs now sits inside a
bare block scope and declares nothing at module level. Four PRs merged into
that file in parallel on 2 September and two of them collided on a top-level
const, which is a SyntaxError: not one assertion in the file runs, on any
branch. A block that declares nothing at module level cannot do that to the
next branch.
tests/site-claims.test.mjs block 12 stopped spelling the units itself. #336
renamed both /pricing section headings and put ParaSign first, and #359
reworded "2 signatures per month" to "2 signatures a month". The block now
finds the headings by product prefix, orders them by position, and lifts each
fact out of the card as a whole phrase, so /about repeats what /pricing says
rather than what this file guesses /pricing says. /about follows the new
wording: "2 signatures a month", "24 hour link expiry", "up to 10 reads per
link".
Still open, deliberately
The eIDAS level (SES on /about, advanced (AES) in the /pricing FAQ) is a
real contradiction and needs a decision, not a copy edit. This branch stops
it spreading and pins that it stays on the one page that has always carried
it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Head elements only, on 50 of the 60 frontend pages:
<title>, meta description, Open Graph, Twitter cards and JSON-LD. No body text, no styling.apply-nav.pyandjs/nav-auth.jsare untouched, and a machine check over all 50 changed HTML files reports 0 diff hunks after</head>in either the old or the new version of the file.Rebased on main
Squashed onto
origin/main(d946752). Main moved a long way while this was open: #328 (homepage head rewritten), #325 (/parasignexists), #331 (docs/brand/messaging.md, and it is now the authority for titles and descriptions), #338, #340, #341, #342, #352, #332, #353, #337 and #333. The diff against main is 52 files: 50 HTML heads, the generator that writes them, and the test that gates them.Two conflicts,
frontend/index.htmlandfrontend/pricing.html, both in the head. Resolved the same way each time: main wins where main already writes to the guide, this branch adds what main does not have./indexkeeps main's title, main's description sentence, main'sSoftwareApplicationnode ("ParaSign by Paramant",BusinessApplication, Community at EUR 0) and main's Organization description ("Dutch company, servers in Germany"). This branch adds the founder, the address, the KvK identifier and the contact address to that Organization node, on every public page rather than on the homepage only, and adds one clause to the description (below)./pricinghad no head work on main at all, so the head comes from this branch, rewritten against the guide.docs/brand/messaging.mdis on main now, so the earlier round's dead source reference is a live one. The head texts follow the guide, not the current body: three of these pages have a body rewrite open in another PR.One drift fixed.
python3 bron-seo/apply_seo_head.py --checkon plainorigin/mainreportswould change: 1 pages, because #328 hand-edited the homepage JSON-LD block the generator owns. Left alone, the next run of the generator would have silently reverted it. The generator now carries that shape (SOFTWARE_OVERRIDES) and keeps the middot instead of flattening it to a hyphen, so the JSON-LD name is the title character for character. On this branch:would change: 0 pages.What the review asked for
1. Who is behind it, in the text a human actually sees. The founder and the legal entity were in the JSON-LD, which no preview in WhatsApp, LinkedIn, Signal or iMessage renders.
og:descriptionis pinned to the meta description by the consistency gate, so it had to go in the description itself.The legal entity is now in the description of all three pages that sell on who is behind it. The founder's name is in one of them,
/about, because that is the page whose own sentence backs it; on/and/pricinghe stays in the Organization node, where the same three fields are now present on every public page.//about/pricing2. No jargon in a description, and no product name assumed known in its first sentence.
/verifysaid "ML-DSA-65 (FIPS 204)" and now says what you get out of it;/signsaid the key never reaches "the relay" and now says it stays on your device. "relay", "envelope",.prmnt, ML-DSA, ML-KEM, FIPS, AES-n and "open-core" are out of every title and out of the first sentence of every description, except on the four pages whose subject is the architecture. Every description opens with the action, never with ParaSign or ParaSend.TOTP is out of the first sentence of
/help,/help/api-key-vs-totp,/help/lost-authenticatorand/help/session-issues; they say "a code from your authenticator app", which is what those articles call it themselves. It is not added to theINTERNALlist: TOTP is RFC 6238 and the word every authenticator app prints, so it is the reader's vocabulary rather than ours, and putting it on the list would force a rename of a page whose own H1 and URL slug areAPI key vs TOTPwhile #333 is rewriting that body.3. A title that promises no more than the page delivers. The old homepage title was "Sign and send without a US server".
/securitylists third-party services and the guide is explicit (section 4, proof 1) that the claim is about the data path and that Resend is the named exception. The title is now main's: "sign and send documents in the EU", which the rules grid backs word for word ("Hetzner Germany, Bunny DNS (Slovenia). No US provider in the data path. Email goes out via Resend"). No head element on any page carries an unqualified no-US claim.4. The free plan is Community in the head too.
/signupsaid "ParaSign Free gives 2 signatures a month";/pricingsaid "Free stays free". Both now say Community, which is whattests/ui-truthfulness.test.mjsrequires of the body and what the guide fixes as the name.5.
/trustsaid three different things at once.<title>and<h1>said "Trust & Verification" whileog:title,twitter:titleand the JSON-LDWebPagename said "Trust & Transparency". No test compared a title with its JSON-LD. One does now, and all four agree.6.
/parashareis byte-identical to main. It is in the PRIVATE set of bothbron-seo/apply_seo_head.pyandtests/seo-contract.test.mjs, so both content gates skip it:git diff origin/main -- frontend/parashare.htmlis empty and the page carries no Organization node.7. No em-dashes, no
PARAMANTin caps. Swept over<title>, description,og:*andtwitter:*on all 60 pages, private and redirect pages included: 0 violations.8. The sentences are pinned now. Previous round's gate pinned
<title>,og:titleandtwitter:titleto each other, so setting all three to "Paramant is ISO 27001 certified and free forever" passed. Eight pages now have their title and description pinned word for word, with the source of every claim named in the file.Sabotage, run on this commit:
<title>on/to "Paramant, the fastest signing tool in Europe",og:titleandtwitter:titleand the JSON-LD name pulled along with itnot ok 12 - the pages that carry the offer say exactly what they are pinned to sayWebPage.nameon/trustto "Trust & Transparency", title and cards left alonenot ok 10 - the title, Open Graph, Twitter cards and JSON-LD say the same thingHead values, and where each claim comes from
Every claim below is printed on the page it appears on, unless a different file is named.
/index.html("Get documents signed and send files safely, from your browser", "Everything runs on servers in Germany"); rules grid "EU soil, EU law: Hetzner Germany, Bunny DNS (Slovenia). No US provider in the data path"; footer entity fromapply-nav.py; "The Community plan is free, forever" frompricing.html/aboutabout.html"founded by Mick Beer, privacy and security researcher"; footer entity and town fromapply-nav.py/pricingpricing.html: "The Community plan is free, forever"; the ParaSend Pro card at EUR 15/mo and the ParaSign Pro card at EUR 49/month, named per product because an unsplit "from 15 euro" reads as if signing starts there; the page-wide "excl. btw" basis/parasignparasign.html(#325): the signing flow, the public verification log, and the Community/Pro/Business split/signsign.html:391"the file and your private key stay in this browser, and the relay only ever sees a hash";sign.html:412"Private key stays on your device";sign.html:686the downloads verify offline. "the document text", not "the file":sign.html:514says "Paramant delivers the encrypted document with the request" and:708that it opens in the recipient's browser, so in Request signatures the encrypted file does leave. Plaintext and key stay local in all three modes/verifyverify.html: in-browser verification, no account, nothing uploaded/vaultvault.html: the file and the passphrase never leave the browser/signuppricing.html: "2 signatures per month", "unlimited receiving", "Forever · no card required"/downloaddownload.html: "last built in March 2026 and is missing 21 protections the web app has ... Use paramant.app until the native app is rebuilt"/securitysecurity.html(Hetzner Nuremberg, EU/Germany GDPR) and its disclosure section/trusttrust.html: the self-hosting section and the LIVE/PLANNED tags on the page/statusstatus.htmlvisible line: "Auto-refreshes every 30s · uptime % calculated from last 24h of checks"/slasla.html, which runs Community to Enterprise/pararulespararules.html/privacyprivacy.html: the stored-data list and the IP retention section/termsterms.html; entity fromapply-nav.py/dpadpa.html, which is an Article 28 processor agreement/licenselicense.html: BSL 1.1 and Change Date 2030-01-01/docsPARAMANT · Documentation/changelogchangelog.htmland its security-relevant marker/ct-logct-log.html: the Merkle tree description/crypto-agilitycrypto-agility.html, the algorithm table (technical page, exempt from the internal-vocabulary gate)/architecturearchitecture.html(technical page, exempt from the internal-vocabulary gate)/docs/paramant-ot-brief/audit-log-exportaudit-log-export.html: Article 30 and burn-on-read/partnerspartners.html, which lists nobody; the future tense is the correction/presspress.htmlcontents/vsvs.html/security/acknowledgementssecurity/acknowledgements.html/helphelp/index.html, which names authenticator setup, backup codes, "session expired, clock drift" and the two extensions/help/api-key-vs-totp/help/authenticator-apps/help/authenticator-setup/help/backup-codes/help/gmail-extension/help/iot-integration/help/lost-authenticator/help/outlook-extension/help/session-issuesAll titles under 65 characters, all descriptions between 50 and 165,
og:*andtwitter:*identical to the title and the description on all 39 public pages, and the founder and the legal name in the Organization node of every one.Head re-check needed after these land
The head texts follow
docs/brand/messaging.md, not the current body, so five open PRs rewrite bodies under a head that is already written for the new text. Each still deserves a look at the head after it merges, because a description that quotes a page has to keep quoting it:/parasign,/parasend,/sign/parasenddoes not exist yet: a new page needs a title, a description and a sitemap entry, and the three gates apply to it the moment the file lands./parasignand/signdescriptions quote the signing flow./about,/security,/trust/aboutand/trustare pinned word for word here;/security's description quotes the jurisdiction table, which #335 moves up the page. If the sentence changes on the page, the pin must change in the same commit./pricing,/signuppricing.html. If a tier price or the Community wording moves,PINNEDfails first, which is the intent./auth/backup,/auth/request-resetand/signup/verified; those pages arenoindexand have no description contract, so only the em-dash and caps sweep applies, and it is clean./docs,/help/docsdescription won the rebase ("compliance docs for Paramant v3.0.0 ... The relay never holds a decryption key"); this branch keeps the title, because main'sog:titlethere was stillPARAMANT · Documentation. On the three/helppages main's head was still the untouched caps version, so this branch's head stands.Also still open and not closed by this PR, because they are body work: the first screen of
/pricingat 390px carries no amount, the homepage H1 does not repeat the title, and and/security's jurisdiction table still carries the unqualified "no US company" row that the guide's section 9 names as an open contradiction (#332 has since closed section 9's third point by putting the give-back sentence on /about). None of them is promoted by any head element in this branch.Green
seo-contract14 pass,ui-truthfulness,site-claims,links,frontend-loading-contract(33 pass, 0 fail, 2 skipped for a missing live server),scripts/check-csp-inline.sh,scripts/check-cache-bust.sh,npx eslint .exit 0,python3 bron-seo/apply_seo_head.py --check=would change: 0 pages.tests/static-sanity.sh: PASS, all ten checks clear, check 10 (commit-style guard) included. No trailer on the commit.