Read this first  Development-grade, single-operator service. This document is a starting draft and it has not been reviewed by a lawyer. It is written to match what the product already discloses about itself, not to reassure you. Last updated 2026-08-19.

The product already says this. So does this page.

Where the two disagree, the product is right and this page is the defect.

Every report mend.rest produces carries a limits list, and that list is inside the facts object the fact_digest is taken over — so the disclosures below are not marketing copy that can quietly drift from the software. They are pinned strings in mend/report.py, reproduced here verbatim, and you can recompute the digest yourself (Verify) to confirm the copy you were handed is the copy that was signed for.

That is the whole method of this page: a privacy policy that says less than the product already admits would be a lie by omission. The paragraphs that follow are the ones most policies bury, put first.

See also Terms and the site map.

1 · The four disclosures that govern everything below

Quoted exactly as the product prints them. Nothing on this page may contradict them.

From the limits of every report

verbatim
Custody“custody is INTEGRITY-ONLY with NO AT-REST ENCRYPTION: submitted content is stored as content-addressed plaintext whose SHA-256 is re-verified on every read, and encryption is refused as UNSUPPORTED rather than simulated”
Tenant isolation“tenant isolation is process and directory permissions only (a per-tenant child process and an 0700 per-tenant state directory); independent adversarial review did not break cross-tenant separation, which is EVIDENCE AND NOT A PROOF, and the host operator can read every tenant's state”
Grade“development-grade: the preregistered effectiveness benchmark has NOT been executed (held-out execution is BLOCKED pending independent steward isolation), so this service makes NO effectiveness, accuracy, or assurance claim”
Deployment“publicly served over HTTPS at api.mend.rest; a single-operator hosted deployment, not a production-grade or highly available service”
Evidence base“the evidence base for this software is fixture data; the open service now receives real submitted work, and no approval covers customer or external data”
Read the fourth one twice. No approval covers customer or external data. That is not a formality: it means the honest thing to submit here today is work you could afford to have read by the person who runs the box.

2 · What is collected

Five things, and the list is meant to be exhaustive.

Email addressGiven at signup. It is used to verify that the mailbox is yours and to send you the sign-in link that issues your key. It is stored lowercased, alongside a folded form of itself (subaddressing and dots collapsed) that exists only so one person cannot silently hold many accounts. No password is ever collected, because there is none.
API keyOnly as a SHA-256 fingerprint. The store's own words: “What lands in SQLite is sha256(plaintext) as hex, and nothing else.” The key itself is shown once, at issuance, and is not recoverable — not by you, and not by the operator, because it does not exist anywhere to recover.
The work you submitThe files you choose to hand to mend for refereeing, plus the commission that declares what they were supposed to satisfy. Stored under custody — which, per the quote above, means content-addressed plaintext with integrity checking and no encryption at rest.
Derived evidenceDigests, verdicts, gap names, the event timeline, the deletion tombstone, and one access-audit row per vault operation. This is the product: an appraisal that left no trail would be worth nothing.
Request sourcesRate limiting observes where a request came from. What is retained from that observation is the next section, because it is the question a policy usually answers with a shrug.
Staged upload bytes (PUT /v1/blobs) are pre-custody: they belong to no task, no deletion receipt covers them, and they expire on their own clock — 10 MB per file, 100 MB per account, and a 24-hour expiry swept lazily when the store is next touched. Custody begins when mend.intake accepts them.

3 · Where a network address is, and is not, retained

Answered from the code rather than from intention. Including the part this page cannot answer.

The access log line

one line per request
What it containsVerb, path with the query string stripped, status, tenant id, key id, method name, and a duration in milliseconds.
What it does notThe bearer, the minted identity token, any header value, the request body, the query string — and no network address. The code says why: what an abuse trail needs is the key id, “an identifier, never the secret — the secret is not even stored”, and anything more is collecting data the incident would not use.
Where it goesThe service's standard error stream, which the host's container runtime captures. How long that capture is kept is host configuration this page cannot read, so it is not claimed here.

Rate limiting

three different answers
API callsKeyed on the key id and the tenant, not on an address — 60 requests per minute per key and 240 per minute per tenant by default. Token buckets in memory, pruned once idle. No address is involved at all.
Report sharingKeyed on the source address the edge vouched for, 5 per 10 minutes. That address lives in memory, in the bucket, and nowhere else. The handler states it: “NOTHING ELSE IS WRITTEN DOWN. The source address fed the rate limiter in memory and stops there…”
SignupThe one place a per-source record is persisted — and it holds sha256 of the address, never the address, beside a window start and a count. The schema comment: “The scope itself is NEVER stored: what lands here is sha256(scope), so a stolen database yields no client addresses.” Expired buckets are deleted on the next write once their window has closed.
Only CF-Connecting-IP is honoured, because the edge overwrites whatever a client sends; X-Forwarded-For is deliberately refused, since a client sets it freely. What this page cannot tell you: the edge provider in front of this service keeps its own connection records under its own retention policy, and mend.rest neither controls nor can report on those. If that matters to you, read Cloudflare's policy, not this one.

4 · What is not done with it

Stated as either a checkable property or an operator commitment, and labelled as whichever it is.

checkableNo cross-customer pooling. Every tenant gets its own child process and its own 0700 state directory; task state is addressed by (tenant, task) and no read path joins across tenants. Per the disclosure above, that is process and directory permissions — evidence and not a proof.
checkableNothing is transmitted anywhere by the product. The runtime “has no shell/network capability by construction”. The only route by which a report leaves your control is the share page, and it requires you to paste it yourself.
checkableNo trackers, no analytics, no third-party script, no cookie. This site's content security policy is default-src 'none' with every source narrowed to 'self', and its pre-deploy gate refuses to ship a tree naming any external origin but the platform API. The same gate fails the build if any shipped script touches localStorage, document.cookie or indexedDB.
commitmentYour work is not used to train models. Labelled amber deliberately: there is no training pipeline anywhere in this codebase for the property to be read off, so this is the operator's word rather than a fact you can verify from the source. The verifiable half is the row above — the product ships no path that sends your content anywhere.
commitmentYour work is not sold, rented, or handed to an advertiser. Same category, same honesty: a commitment, not a proof.
The distinction between the two chips is the point of this whole service. A claim you can check and a claim you must take on trust are different objects, and a page that printed them in the same typeface would be doing the thing mend.rest exists to refuse.

5 · Operator access, stated honestly

This is the section a normal policy hides. It is not hidden here.

The host operator can read every tenant's state. Isolation is a per-tenant child process and an 0700 per-tenant directory — operating-system permissions, not cryptography. There is no at-rest encryption, and when something asks for it the vault refuses rather than pretending: at_rest_encryption: UNSUPPORTED, raised as Unsupported("at-rest encryption is unavailable in the local reference profile"). A simulated guarantee would be worse than none, which is why you are reading this instead of a padlock icon.

Independent adversarial review did not break cross-tenant separation. That is evidence, and it is not a proof, and the product says so in the same breath every time it says the first half.

What is true alongside it

not a consolation, a constraint
Every access is recordedEach vault operation appends a notrest.vault.access/1 row to an append-only access-audit.jsonl: a monotonic sequence number, the tenant, the task, the epoch, the actor, the operation, and a digest of the request. The row carries content_included: false — the audit trail records that something was touched and by whom, never what it said.
Logs carry types and countsNever content, never a credential. See section 3 for the exact fields of the one log line this service writes.
Deletion genuinely purgesAnd returns a signed receipt naming what was purged and what append-only history remains. See section 6.
Identity is local HMAC“Phase 3 identity uses local symmetric HMAC; no HSM, TEE, or public signature”, and “proof is local structural SHA-256 without external witness”. There is no third party attesting to any of this, and no public-key signature an outsider could check without the secret.
The threat model does not include the person holding the box. Nothing on this page should be read as a claim that it does.

6 · Retention and deletion

What mend.deletion removes, what it deliberately keeps, and the clocks that run on their own.

mend.deletion

confirm=true, then a receipt

Deletion purges the private material of a task: the report, the commission, the intake, the execution claim, the repair text and repair node, the acknowledgement, the choice receipt, the runtime observations, the effects, the interventions, the candidate, the independent verification, the appraisal, the proof receipt digest, the publication, and the workspace hashes. The stored content is removed from the vault in the same act.

What comes back is a mend.deletion-receipt/1 with complete: true, the owners that acted, the workstream it released, and a digest over its own sealed body — and one limitation, quoted here exactly as the receipt states it:

Receipt limitation“kernel/proof append-only history, digest-only mend lifecycle events, and this deletion tombstone are retained”
That retention is deliberate and it is disclosed in the receipt itself, not discovered later. An append-only history that could be edited to remove a record would not be an append-only history, and the evidence value of every other report would collapse with it. What remains is digest-only: identifiers, sequence, and hashes. A deleted task still answers mend.status, mend.events and mend.deletion, and refuses everything else — the tombstone is readable on purpose. Replaying the receipt returns the original sealed bytes inside an envelope that says it is a record of what happened then, not a claim about now.

Clocks that run without you

defaults; the operator can set each one
Staged upload bytes24 hours, swept lazily. 10 MB per file, 100 MB per account.
Verification link24 hours. Stored as a digest, with separate columns for “already used” and “superseded by a newer link”.
Unverified signup48 hours, after which the tenant is reclaimed.
Idle, never-used account30 days, after which the tenant is reclaimed and its keys revoked.
Revoked key rows30 days, then pruned on a later issuance. A pruned key goes on being refused by absence, and no plaintext exists anywhere that could re-create the row.
Signup source bucketsDeleted on the next write once the window has closed. They hold a hash, never an address.
A reclaimed tenant keeps its row and its address with a reclaimed_at stamp rather than being deleted, so a reclaimed account cannot hold an address hostage: the person behind it can sign up again with the same address. There is no DELETE FROM tenants in the account store, by design.

7 · Third parties

Named in prose and never linked from here, because this site loads nothing from anyone.

CloudflareFronts the public surface. This portal is a Cloudflare Worker serving static pages, and api.mend.rest reaches the platform through a Cloudflare tunnel. Requests therefore traverse Cloudflare's edge, which keeps its own records under its own policy — see section 3.
A mail relayYour address is handed to the operator's configured mail transport for one purpose: delivering the confirmation and sign-in link. The transport is an operator setting (an SMTP relay or an HTTPS relay endpoint), so this page cannot name the vendor without guessing, and does not. Relay credentials never leave the process and are deliberately excluded from every error message.
StripeDonations only. The donate control links out to Stripe's own hosted checkout, on Stripe's domain, in a new tab. mend.rest never sees, receives, or stores a payment detail, and no surface on this site collects one — the pre-deploy gate enforces that the checkout origin can only ever be a link target, never a script, style, image, font, or fetch origin.
There is no analytics vendor, no error-reporting vendor, no font CDN, and no advertising network, on this site or in the platform. That is checked at build time rather than promised: a shipped tree naming any origin outside the allowlist fails the gate.

8 · Report sharing is opt-in, and only opt-in

Nothing is transmitted by the product. Ever. Sharing is an act you perform.

Every report carries one sentence about sharing, in its presentation block rather than its facts, and here it is verbatim: “Sharing this report is optional and nothing is sent unless you do it yourself: paste it at https://mend.rest/share if you would like it to help improve the product.”

That is the whole sharing mechanism. Automatic collection is refused, and the share endpoint has no way to obtain a report other than being handed one — consent here is not a promise made on a page, it is a property of the endpoint.

What a share storesA schema name, the time it arrived, your own redacted declaration, an optional note of at most 500 characters, and the report you pasted. Nothing else — not your address, not your key, not your tenant.
RedactionHappens in your browser, before anything is transmitted, which is the only place it can happen without us having seen the unredacted form first. The bridge records your declaration as a declaration; it does not audit the claim.
RetentionIndefinite. Shared reports land in a per-day file beside the tenant directories and no code expires them. Share only what you are content for the operator to keep.
A report can carry workspace file names. That is precisely why sharing is a deliberate act performed by a human with the report already in their hands, rather than anything the product does on your behalf. If you would rather nothing be shared, do nothing: the default is that nothing leaves.

9 · What you can do

Each of these is a method with a receipt, not a support request.

mend.exportTake your data out. A first-class method with its own receipt, not a favour.
mend.deletionPurge a task and receive the receipt described in section 6.
Revoke a keyFrom the Dashboard, at any time. A revoked key is refused on the next request; there is no cached grace period.
Submit nothingThe most effective control on this list, and the honest recommendation while “no approval covers customer or external data” remains true. Fixture data works for evaluating the service.
Ask the operatorFor anything this page does not cover, including account closure: do@not.rest
What this page is, and what it cannot tell you