Security & trust

How the record stays trustworthy.

A record is worth exactly what it can prove. This page lists the properties of a Pacts record and of the systems around it — and, just as plainly, what we don’t have yet.

The record

What makes an acceptance record worth anything.

A record is only as good as what can be proven about it afterwards. These properties are designed in, not added on.

Append-only

Acceptance records and document versions are written once. There is no code path that updates or deletes them — not for the sender, not for the recipient, not for Pacts.

Captured server-side

Time, IP address and browser are recorded by our servers at the moment of acceptance. A recipient cannot influence what is written.

Exact text, hashed

Every version of a document is stored immutably with its SHA-256 hash; the record carries the hash of the text the recipient saw. Every certificate issue recomputes it and says whether it still matches.

One affirmative act per document

The full text is shown in the flow; the recipient ticks “I have read and agree” for each document and selects Accept. Consent is specific, never bundled.

A certificate that is a document

The Certificate of Acceptance is generated server-side as a PDF — issuer, certificate number, attestation, the particulars, the integrity check, and the exact text as an appendix.

Access

No one talks to the database but our servers.

The browser never reads or writes records. Every access goes through server code, where the evidence is captured.

Database rules deny everything

Firestore’s security rules are deny-all for reads and writes. The only client-side Firebase surface is sign-in; all data access runs on the server with the Admin SDK.

Sessions

Sender sessions are httpOnly, Secure, SameSite cookies with a 14-day maximum. Signing out revokes the session server-side — on every device, not just the one you used.

Sign-in

Email and password, or Google sign-in. Passwords are handled by Firebase Authentication and are never visible to Pacts.

Recipient links

Each recipient gets a private link carrying a 32-byte random token. Optionally, a one-time code emailed to them must be entered before the acceptance is recorded — proof of control of the inbox at that moment.

Abuse controls

Built to be hit by strangers.

The acceptance and sign-in endpoints are public by design, so they are rate-limited and the codes they issue are short-lived.

Rate limits

Sign-in and session creation: 10 per minute per IP. Acceptance submissions: 20 per minute per IP. One-time code sends: 5 per 10 minutes per contact.

One-time codes

Six digits, stored only as a SHA-256 hash, valid for 10 minutes, burned after 5 wrong attempts, and deleted automatically by a database time-to-live.

Transport and headers

HTTPS everywhere with HSTS (two years, preload, subdomains). Pages cannot be embedded in other sites (frame-ancestors ’none’), so an acceptance cannot be clickjacked. Content-type sniffing is disabled.

Private links stay private

Recipient pages are excluded from search engines (robots.txt and X-Robots-Tag) and send no referrer to any site they link to, so a token never leaks through a link or an index.

Where data lives

Hosted on Vercel, stored in Google Cloud, emailed through Resend.

Data is encrypted in transit (TLS) and at rest (Google Cloud’s default encryption). The sub-processors below are the same list our Privacy Policy and DPA carry — it cannot drift.

ProviderWhat they doWhere
Google Cloud / FirebaseApplication hosting, authentication, and the Firestore database where all records are stored.United States (us-central1)
ResendDelivery of transactional email: acceptance links, reminders, one-time verification codes, and notifications.United States
VercelApplication hosting and edge network.United States

If you are in the UK, EEA or Switzerland, transfers rely on the European Commission’s Standard Contractual Clauses together with the providers’ own transfer frameworks — see the Privacy Policy and the Data Processing Addendum.

Not yet

What we don’t have, said plainly.

SOC 2 / ISO 27001

Not certified. We describe our controls here instead of claiming a badge we don’t hold.

EU data residency

Records live in the United States (see below). Transfers from the UK and EEA rely on the Standard Contractual Clauses.

SSO for senders

Google sign-in is available; SAML/OIDC is not.

Public certificate verification

A certificate can be re-issued from the record at any time; a public endpoint to verify one without signing in is on the roadmap.

If one of these is a requirement for you, tell us — it shapes the roadmap.

Report a vulnerability

No system is perfectly secure. If you believe you have found a weakness, write to support@pacts.io and we will respond.

Privacy requests

Access, correction, export or deletion requests go to privacy@pacts.io. We respond within one month. Acceptance records themselves are retained as evidence of the act they document.

Send this page to whoever asks “is a click safe?” — then put one standard agreement on Pacts and see the record for yourself.

Send your first terms