Pin the site's ten heaviest claims to the code that makes them true - #327
Merged
Conversation
The pruning plan of 1 September asks that every promise on the site be nailed to a test that fails when the promise stops being true. The gate existed (seo-contract, ui-truthfulness) but only covered markup and two pages. tests/site-claims.test.mjs now reads the constant, name or count from the source that enforces it and checks the page says the same thing. Four claims turned out to be wrong when measured, and the pages change to what the code shows: - security and crypto-agility said "3 KEMs and 18 signatures loaded in production"; bootstrap.js registers 17 signatures, and only in CRYPTO_MODE=extended. The default is core, which loads ML-KEM-768 and ML-DSA-65. Both pages now say so. - security promised a 30-minute account lockout after ten failures; no such code exists (admin/server.js, relay.js). Sentence removed. The numbers that do exist (session 1 h, TOTP 30 s, 5/IP and 10/email per 15 min) are pinned. - pricing quoted a 99.9% Enterprise SLA; sla.html commits to 99.95%. The SLA page also described a 60-second probe from multiple EU locations and uptime history in the CT log; neither exists. It now describes the hourly product-heartbeat workflow and /status. - press said twenty findings across two audits, fully resolved before public release. The /docs table lists three audits and forty findings, and docs/security-audit-2026-04.md still marks three as in progress or open. trust and dpa linked to /security#audits, which does not exist; they now point at /docs#audits. security's "IP log retention: 7 days" had no rotation config behind it and now promises no period. The rest of the inventory, 60-odd claims with their status, is in docs/site-claims.md so the follow-up is visible. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XJk2nCLCLmi3F71qkCUn7N
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XJk2nCLCLmi3F71qkCUn7N
…ogging The measurement paragraph on /sla, new in this branch, said availability is measured with hourly GET /health checks from the product-heartbeat workflow. That workflow never calls /health: it loads paramant.app in a browser and pushes a transfer and a signature through relay.paramant.app, and the four sector relays are not in it. The only thing that polls /health on all five relays is /status, from the visitor's browser. The paragraph now says exactly that, and test 8 reads the live job (suites, targets, no /health, no sector host) and status.inline1.js (five sectors, fetch /health) so the text has to change when the monitoring does. The IP-logging row on /security still described nginx access logs that follow log rotation while deploy/nginx-paramant-live.conf switches access logging off on every server block that serves the site or a relay. The row now says that, and test 9 fails on any access_log that is not off. Whether the server matches the file is noted as unprovable from the repository. docs/site-claims.md gains the third contradiction the audit numbers expose: the /docs#audits table counts 40 findings across three audits, SECURITY.md lists 50 across four. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XJk2nCLCLmi3F71qkCUn7N
The line-comment regex cut every source line at its first "//", so 'https://relay.paramant.app/health' in tests/transfer-canary.test.mjs became 'https:'. Test 8 asserts the canaries do not call /health; against a health check written as a full URL it was asserting on a truncated file. Walk the source instead and copy string, template and regex literals through untouched. Same rule for the workflow YAML, where "#" only opens a comment at the start of a line or after whitespace. Proof: adding fetch('https://relay.paramant.app/health') to the transfer canary now fails test 8; with the old stripper the same sabotage passed.
Apolloccrypt
force-pushed
the
chore/site-claims-tests
branch
from
September 2, 2026 14:16
038b266 to
76fdcc2
Compare
Apolloccrypt
added a commit
that referenced
this pull request
Sep 2, 2026
Run 33624449015 this morning reported all four steps green. Two of them proved
nothing, and the log says so:
ok 1 - parasign: an envelope is created, signed and notarised # SKIP PARASIGN_CANARY_KEY not set
duration_ms: 1.284603
ok 2 - parasign: the signed document comes back stamped # SKIP PARASIGN_CANARY_KEY not set
duration_ms: 0.115257
# pass 1
# fail 0
# skipped 2
node --test prints a skipped test as `ok N - name # SKIP reason` and counts it
in `# pass`. Both canaries used { skip: KEY ? false : 'reason' }, so a missing
secret meant a skip, a skip meant ok, and ok meant a green tick. The duration is
the part that cannot be argued with: creating an envelope, signing it and
verifying an ML-DSA-65 signature does not happen in 1.28 milliseconds. Nothing
left the runner. The failure filter had the same blind spot from the other side,
scanning for ^(x|not ok|AssertionError|fail) while a skipped test begins with ok.
Neither secret exists. gh secret list returns four names, none of them a canary
key, and there are no environment or dependabot secrets. So the keyed ParaSend
route and the entire ParaSign product have never been checked, not once, by
anything.
THE RULE
A monitoring step may never have an escape hatch. If what it needs is missing,
that is red, with the name of what is missing. A reason belongs in the error
message, not in the verdict.
WHAT IS HERE
scripts/heartbeat/, four steps, no test runner and therefore no pass/skip
semantics in the way:
surface /health; /v2/health/deep, whose three possible worlds are told apart
from the answer (405 mode-dropped, 200 in full mode, 401 behind the
internal gate) and whose body is asserted because the handler
answers 200 even when overall is red; and the six hosts x two ParaID
issuance paths, so the deny inserted by hand into nginx on 01-09 is
checked hourly from outside. A 400 there means the handler is
reachable again.
parasend both routes, anonymous and keyed. Upload, fetch, compare the bytes,
require the burn. Plus a payload that does not match its hash, which
must be refused before storage.
parasign-receipt /v1 with the psk_test_ key: envelope to completed, then
the .psign verified offline - the notary counter-signature against
the key published at /v2/pubkey rather than the key printed inside
the receipt, and every party signature against a message rebuilt by
the relay's own signMessageBytes.
parasign-public-sign /v2, the route a recipient's browser actually posts to,
which the sandbox auto-signer never touches. It submits a signature
that does not verify and requires a 400 first, because a relay that
rubber-stamps would sail through every positive check ever written.
Then it signs for real, verifies offline, and folds the new CT leaf's
inclusion proof back to the published tree head with ctNodeHash.
Every step writes heartbeat-evidence/<step>.json with ids, hashes, statuses and
timings, uploaded as an artifact on every run. runStep fails a step that recorded
no proof even when nothing threw, so a step cannot pass by doing nothing again.
Failure emits one ::error:: annotation, which GitHub renders above the log, and
opens or comments on a single issue titled "Heartbeat rood"; green closes it.
ONE THING FOUND WHILE BUILDING IT
@noble/post-quantum 0.6.1 takes verify(signature, message, publicKey). The
ParaSign canary called verify(publicKey, message, signature), which throws a
RangeError on the installed version. Even with its secret set it could never
have passed. The argument order now lives behind named wrappers in one place,
with a round-trip check at import.
ALSO
The hourly half of product-heartbeat.yml moves here, so there is one alarm with
one evidence artifact instead of a job whose green tick meant different things in
different steps. product-heartbeat.yml keeps the browser suite as the
pull-request gate. The two canary suites are deleted; their coverage is in
scripts/heartbeat/ and they carried the bug. The name-based exclusion they needed
in test.yml goes with them, which is how a suite ends up running in no workflow
in the first place.
docs/heartbeat.md: what each step proves, which secrets are needed and why, and
how to run it by hand.
ONE CLAIM ON THE SITE HAD TO MOVE WITH IT
site-claims.test.mjs (#327) pins the SLA measurement paragraph to the workflow
that makes it true, and it caught this change, which is exactly what it is for.
The old hourly run deliberately did not call /health and did not touch the
sector relays, and the page said so. The new one calls GET /health and the deep
readiness check, and reaches all six hosts for the ParaID deny check. So the
paragraph now says that, and says plainly that reaching the four sector relays
to confirm a retired route stays refused is not an uptime measurement. The test
moved to heartbeat.yml with assertions in both directions: if a step stops
touching its product, the sentence has to go.
Apolloccrypt
added a commit
that referenced
this pull request
Sep 2, 2026
Rebased onto a main that gained the site-claims suite. Two of its ten gates disagreed with this branch, both because they pinned something this PR changes on purpose. Gate 5 pinned the tier name Free in two sentences on /privacy. The numbers it guards are unchanged and still read out of tiers.js; only the name moved, and the remaining Free on the retention line moved with it so /privacy does not carry two names for one plan. Gate 10 required the homepage to say 'N encrypted CLI tools'. A gate that forces a page to MAKE a claim is the wrong invariant, and this is the claim the July audit found unobtainable: paramant-solutions is private, so a visitor cannot get the tools, and the sentence came off the buyer homepage. Retargeted to what must actually stay true: any page stating a tool count must state the catalogue's real one, checked across every page under frontend/ rather than the homepage alone. Sabotage-checked in both directions: a page claiming 7 fails, a page claiming 10 passes. The pricing conflict from the rebase kept both sides: main's correction of the Enterprise SLA to 99.95 percent, and this branch's tier rename. The homepage quoted 99.9 percent in two places and now matches.
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 actually came for, the jurisdiction table, seven screens down. /trust never said who it was for. They now run the order the messaging guide fixes (docs/brand/messaging.md): what this is, who it is for, who is behind it, a next step, then the proof including the honest limits. /about is the founder page. The lede is plain language first: 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. Post-quantum arrives after that sentence, as the reason it holds up, not as the opening. Under it, in the first phone screen: who it is for (small offices that sign and send confidential papers, and the person who has to check a supplier), then Mick Beer, privacy and security researcher, founder of Paramantis Solutions B.V., then two buttons. Measured at 390px: the last of those sits at y=665, inside the first screen. The section number "00" is hidden in the mobile override instead of landing under the H1 as a stray number. Below that, the split itself: ParaSign Free and ParaSend Free on one side, ParaSign Pro, Business and Enterprise and ParaSend Pro and Enterprise on the other, named and priced as /pricing names and prices them. The cryptography section keeps every word and moves to 03, where it reads as evidence for the paragraph above rather than as the argument itself. /security answers "why would I trust you" before it answers "how does it work". The hero says it without jargon: even if our own server is broken into, nobody can read your documents, because they are encrypted on the device before they leave it. The eyebrow is EVIDENCE, not DEFENSE IN DEPTH, and the word relay no longer appears above the fold undefined. A four-card block says what each proof means and links to where the reader checks it. The jurisdiction and privacy table moves up under it, in main's wording, including the corrected IP-logging row. The EU-law card no longer says the CLOUD Act is "not applicable" full stop: it says no US storage and no US parent company, and it names the third-party services in front of the site, Cloudflare among them, that the out-of-scope list further down already carries. The hero promises "who audited it", so the page now answers it: three external audits in April 2026, two by R. Zwarts and one by Ryan Williams of Smart Cyber Solutions, with the finding counts and resolving commits on /docs#audits and the findings in SECURITY.md, and the plain statement that the reports themselves are not published. The pointer that sent the reader to /architecture for audit history is gone, because /architecture sends them back here. The page ends in a next step, two buttons, instead of only a disclosure address. /trust says who it is for, in the hero. The lede named the reader's relay before it named the reader. It now opens on the audience: organisations running Paramant on their own server, and anyone who has to check a supplier, with hosted users pointed at /security. The tab title said "Trust & Transparency" while the H1 said "Trust & Verification"; they match now. The audit paragraph names its auditors, links the table on /docs#audits and SECURITY.md, and says the reports are not published. The thirty-one em-dashes are gone, per the house style. The eIDAS wording is not spread. /about calls a ParaSign signature a Simple Electronic Signature; the /pricing FAQ calls it advanced (AES). Those are different levels under eIDAS and settling it needs its own round, so the sentence stays on the one page that has always carried it. security.html does not get a second, competing level, and a test now asserts it does not. No claim on any of the three pages is new. The sentences the copy rests on are pinned in tests/ui-truthfulness.test.mjs: the founder name and title, the three /about proof sentences, the SES limit on /about only, the CLOUD Act row, the same-cryptography-on-every-plan sentence on /pricing and /security, the certification limit, the audit sentences and the "reports are not published" line on both pages, the /trust title matching its H1, and what each hero has to say above the first section heading. tests/site-claims.test.mjs gains an eleventh block: the tier facts on /about are read out of the /pricing tier cards (signature allowance, both link expiries, read count, device count, Enterprise SLA) and asserted, so /about cannot drift from what is sold. That block also catches the number this branch had wrong: /about said the ParaSend Enterprise SLA was 99.9%, /pricing and /sla say 99.95%. Rebased on main, so the four corrections #327 made are kept: 17 signature schemes with the core/extended caveat, no account-lockout promise, the IP-logging row citing access_log off in deploy/nginx-paramant-live.conf, and the /trust audit link pointing at /docs#audits. Mobile: 390px, no horizontal scroll on any of the three. index.html, apply-nav.py and js/nav-auth.js are untouched. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XJk2nCLCLmi3F71qkCUn7N
Apolloccrypt
added a commit
that referenced
this pull request
Sep 2, 2026
main moved while this branch was open. Rebased onto 99909a1 and folded what arrived into the CHANGELOG section, because a release section that is a snapshot of the moment it was written is the exact failure this PR is fixing. New in the section: the ParaSign product page at /parasign (#325), the messaging guide (#331), the homepage rewrite for a buyer (#328), the site claims pinned to the code that makes them true (#327), the heartbeat that cannot be green without evidence (#338), and the route suites that boot a real relay.js (#341). Count in the intro goes from 268 commits and 52 PRs to 277 and 58, and the intro now says it was rebased rather than pretending it was written in one pass. #341 is worth naming for what it is: point 3 of the toekomstbestendigheid report was that relay.js, 6488 lines and 68 routes, was loaded by no unit test at all. It is now loaded by the route suites. That point is not closed, but it is no longer zero. Two conflicts, both resolved toward main's newer structure: - product-heartbeat.yml: #338 moved the live job out into heartbeat.yml. Took main's file whole and applied the Node 24 bump to both files instead, so the bump follows the job rather than the filename. All seven node-version entries across the five workflows now read '24'. - test.yml: #341 added a second silent-suites gate for the route job and set both expected sets to empty. Kept main's exclusion lists and applied --test-reporter=tap to both steps. That second one matters more after the rebase than before. With a non-empty expected list, the spec reporter made the gate fail, which is how it was found. With an empty expected list, the spec reporter makes it PASS: the grep finds nothing, silent is empty, and a gate that can no longer see anything reports green. A dead gate that reports green is precisely what these two gates exist to prevent, so both now pin the reporter rather than inherit a Node default. Tests after the rebase, on Node 22 and again under node:24-alpine: relay 175, admin 40, root 145 (143 pass, 2 pre-existing skips), both silent-suite gates empty as expected. static-sanity PASS including the style guard, bash -n and eslint clean. The root job now runs npm ci first, per #338; tests/README.md and the local commands in docs/RELEASE.md match what CI does.
Apolloccrypt
added a commit
that referenced
this pull request
Sep 2, 2026
Second pass on the review of PR #333, rebased on main (#324, #327, #328, #331, #342). /docs - The buyer line is pinned to the visible paragraph. The old assertion matched the same words in four meta tags, so deleting the paragraph left the test green. Proven by sabotage, both ways. - The buyer gets a real button to /pricing beside Quick start, same size, same row. Quick start stays the primary CTA the messaging guide asks for; the pricing button is the outlined one. - Two sentences that ran on double colons now read as sentences, and the ADR range no longer uses an en-dash. /help - "What does it cost?" names the numbers /pricing prints: ParaSign Community free forever, no card, 2 signatures per month, and ParaSign Pro at 49 euro a month excl. btw (59.29 incl.) with 100 signatures. Each half is pinned to the card it was quoted from. - "Pay for volume, never for security" is off the support page. The fact behind it stays, quoted from /pricing: every plan gets the same encryption, the same post-quantum signatures and the same public proof log. A test now fails if the sales line comes back. - "Where does my data live?" is three readable sentences instead of a flattened compliance table: Hetzner Nuremberg, EU law and the GDPR, no US provider in the data path, and email via Resend as /privacy sets out. Scoped to the data path per proof 1 of the messaging guide, so the unqualified "no US company" row from /security is not repeated here while that contradiction is open (guide section 9). - The em-dash sweep on api-key-vs-totp and lost-authenticator now covers the H1, the tab title, the meta description and the body, not only the lede. A test pins all three help pages. /developer - The page is noindex and only reachable once signed in, so the lede addresses the developer reading it, not the buyer who sent them. The plan boundary for API access stays, and a test forbids the buyer phrasing coming back. Tests: links, seo-contract, ui-truthfulness, site-claims, frontend-loading-contract, navigation-shell, csp-inline, cache-bust, eslint and static-sanity all pass. Every new pin was sabotaged one at a time and went red.
Apolloccrypt
added a commit
that referenced
this pull request
Sep 2, 2026
Second pass on the review of PR #333, rebased on main (#324, #327, #328, #331, #342). /docs - The buyer line is pinned to the visible paragraph. The old assertion matched the same words in four meta tags, so deleting the paragraph left the test green. Proven by sabotage, both ways. - The buyer gets a real button to /pricing beside Quick start, same size, same row. Quick start stays the primary CTA the messaging guide asks for; the pricing button is the outlined one. - Two sentences that ran on double colons now read as sentences, and the ADR range no longer uses an en-dash. /help - "What does it cost?" names the numbers /pricing prints: ParaSign Community free forever, no card, 2 signatures per month, and ParaSign Pro at 49 euro a month excl. btw (59.29 incl.) with 100 signatures. Each half is pinned to the card it was quoted from. - "Pay for volume, never for security" is off the support page. The fact behind it stays, quoted from /pricing: every plan gets the same encryption, the same post-quantum signatures and the same public proof log. A test now fails if the sales line comes back. - "Where does my data live?" is three readable sentences instead of a flattened compliance table: Hetzner Nuremberg, EU law and the GDPR, no US provider in the data path, and email via Resend as /privacy sets out. Scoped to the data path per proof 1 of the messaging guide, so the unqualified "no US company" row from /security is not repeated here while that contradiction is open (guide section 9). - The em-dash sweep on api-key-vs-totp and lost-authenticator now covers the H1, the tab title, the meta description and the body, not only the lede. A test pins all three help pages. /developer - The page is noindex and only reachable once signed in, so the lede addresses the developer reading it, not the buyer who sent them. The plan boundary for API access stays, and a test forbids the buyer phrasing coming back. Tests: links, seo-contract, ui-truthfulness, site-claims, frontend-loading-contract, navigation-shell, csp-inline, cache-bust, eslint and static-sanity all pass. Every new pin was sabotaged one at a time and went red.
Apolloccrypt
added a commit
that referenced
this pull request
Sep 2, 2026
Second pass on the review of PR #333, rebased on main (#324, #327, #328, #331, #342). /docs - The buyer line is pinned to the visible paragraph. The old assertion matched the same words in four meta tags, so deleting the paragraph left the test green. Proven by sabotage, both ways. - The buyer gets a real button to /pricing beside Quick start, same size, same row. Quick start stays the primary CTA the messaging guide asks for; the pricing button is the outlined one. - Two sentences that ran on double colons now read as sentences, and the ADR range no longer uses an en-dash. /help - "What does it cost?" names the numbers /pricing prints: ParaSign Community free forever, no card, 2 signatures per month, and ParaSign Pro at 49 euro a month excl. btw (59.29 incl.) with 100 signatures. Each half is pinned to the card it was quoted from. - "Pay for volume, never for security" is off the support page. The fact behind it stays, quoted from /pricing: every plan gets the same encryption, the same post-quantum signatures and the same public proof log. A test now fails if the sales line comes back. - "Where does my data live?" is three readable sentences instead of a flattened compliance table: Hetzner Nuremberg, EU law and the GDPR, no US provider in the data path, and email via Resend as /privacy sets out. Scoped to the data path per proof 1 of the messaging guide, so the unqualified "no US company" row from /security is not repeated here while that contradiction is open (guide section 9). - The em-dash sweep on api-key-vs-totp and lost-authenticator now covers the H1, the tab title, the meta description and the body, not only the lede. A test pins all three help pages. /developer - The page is noindex and only reachable once signed in, so the lede addresses the developer reading it, not the buyer who sent them. The plan boundary for API access stays, and a test forbids the buyer phrasing coming back. Tests: links, seo-contract, ui-truthfulness, site-claims, frontend-loading-contract, navigation-shell, csp-inline, cache-bust, eslint and static-sanity all pass. Every new pin was sabotaged one at a time and went red.
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.
What
The pruning plan of 1 September (
Snoeiplan, "wat er juist bij moet", point 3) asks that every promise on the site be nailed to a test that fails when the promise stops being true. The gate existed (seo-contract.test.mjs,ui-truthfulness.test.mjs) but covered markup and two pages. This PR addstests/site-claims.test.mjs: ten tests that read the constant, name or count from the source that enforces it and check the page says the same thing. Node builtins only, so it runs in the existing "Root integration suites" job.The full inventory (every factual claim on the 38 public pages, with the test that pins it or UNCOVERED) is in
docs/site-claims.mdso the follow-up is visible.What turned out to be wrong when measured
relay/crypto/bootstrap.jsregisters 3 KEMs and 17 signatures, and only inCRYPTO_MODE=extended;.env.exampledocumentscore(ML-KEM-768 + ML-DSA-65) as the defaultadmin/server.jsorrelay/relay.jssla.htmlcommits to 99.95%.github/workflows/product-heartbeat.yml, hourly: a browser run of paramant.app plus the transfer and ParaSign canaries againstrelay.paramant.app. None of the three callsGET /health; the four sector relays are not in the run./status(frontend/js/status.inline1.js) is the only thing that fetches/health, on all five relays, from the visitor's browser. The CT log holds key and transfer commitments/statusdoes/docs#auditstable: three audits, 14 + 6 + 20 = 40 findings, 4 critical;docs/security-audit-2026-04.mdstill marks findings 4, 6 and 14 as in progress or open/security#audits("the findings and patch timeline are on the security page"); dpa linked to plain/security("see security audit summary")/securityhas noid="audits", so the trust link lands at the top of a page without the table; the table isid="audits"infrontend/docs.html/docs#audits, and the trust link text reads "docs page"deploy/;nginx-paramant-live.confhasaccess_log offon every server block that serves the site or a relayWhat is pinned and now goes red
bootstrap.js,impls/*), and every page that names a set names these.registerKEM/registerSigcalls; a stale count anywhere on the page fails.encryption.js,crypto-wasm/src/lib.rs,ct-hash.js,sign-flow.js,vault.js.MAX_BLOBdefault andtiers.js file_mb.tiers.js view_ttl_ms.admin/server.jsandtotp.js; the lockout sentence stays out until code exists./docs#auditstable and the audit document's summary line; "fully resolved" is forbidden while that document lists open findings.sla.html; the measurement text may only describe what exists: the live job runs the three suites against paramant.app and relay.paramant.app (read from the workflow), none of them and no workflow step calls/healthor a sector host, andstatus.inline1.jsfetches/healthon five sectors. The page must say the sector relays are not in the hourly run and that/statuspolls all five from the browser.access_loginnginx-paramant-live.confisoffand every site or relay block carries it; the row cites that file; no retention number without a rotation config.developer-tools.jscatalogue.Mutation check (locally, reverted): changing "17" to "18" on crypto-agility, 99.95 to 99.9 on pricing, "one hour" to "two hours" on security, the heartbeat cron to daily, and the press count back to "twenty across two" each turn the corresponding test red. After the review fix, eight more, each failing exactly the intended test: /sla claiming "automated HTTP health checks" (8), a
curl health.paramant.app/healthstep added to the live job (8),fetch(RELAY + '/health')added to the transfer canary (8), a sector removed fromstatus.inline1.js(8), the sector caveat removed from /sla (8), oneaccess_log offchanged to a log path (9), oneaccess_log offdeleted (9), the old IP-logging row restored (9).Second review round: the comment stripper
The reviewer found that test 8 read its sources through
src.replace(/\/\/.*$/gm, '').That cuts every line at its first
//, including the one inside a URL, soconst RELAY = (process.env.PARAMANT_RELAY_URL || 'https://relay.paramant.app')in
tests/transfer-canary.test.mjsbecameconst RELAY = (process.env.PARAMANT_RELAY_URL || 'https:.The assertion under it (
the canaries must not call /health) was thereforereading a truncated file: a health check written as a full URL would have been
stripped away before the match ran, and the test would have passed on nothing.
Fixed in
76fdcc2with a string-aware walk (stripJsComments) instead of aregex: string, template and regex literals are copied through untouched,
//and
/* */are dropped. Node builtins only, so the suite still needs no parserdependency. The workflow YAML gets the same treatment through YAML's own rule,
where
#only opens a comment at the start of a line or after whitespace.The two other uses of the old regex, on
relay/crypto/bootstrap.jsin tests 1and 2, were switched over as well.
Sabotage proof, all reverted:
await fetch('https://relay.paramant.app/health')added to the transfer canaryhttps:)sla.htmlcommits to 99.95%/slaTests
Re-run on
76fdcc2, rebased onmain(which now carries #324 navigation,#326 billing brake, #329 rust-1.98 binding and #330 signals). The rebase was
clean and
python3 frontend/apply-nav.pyreported no change, so the pages onthis branch already carry the #324 nav.
node --test tests/site-claims.test.mjs: 10/10 passgrep -L "from 'playwright'" tests/*.mjs, canaries excluded, includes links, seo-contract, ui-truthfulness, site-claims and frontend-loading-contract): 120 tests, 118 pass, 2 skipped, 0 failbash tests/static-sanity.sh: PASSbash scripts/check-commit-style.sh: OKNot in this PR
frontend/apply-nav.pyandfrontend/js/nav-auth.jsuntouched (spoor B2).docs/site-claims.mdfor a decision: the BUSL Change Date (LICENSEsays 2029-01-01,license.htmlandterms.htmlsay 2030); the/docs#audits"All resolved" rows versus the audit document; and the audit totals (the/docs#auditstable, which press, trust and the DPA are pinned to, counts 40 findings across three audits, while SECURITY.md, which the table cites as the full record, lists four review sections: RAPTOR 10, Zwarts 14, Zwarts 6, Williams 20 = 50).deploy/nginx-paramant-live.confis not provable from the repository (SECURITY.md says the edge-facing config insites-enabled/is not in git;nginx-paramant-public.confcarries noaccess_logdirective). Noted indocs/site-claims.md; not checked on production, which this branch does not touch.