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.
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.
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.
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.
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.
| Provider | What they do | Where |
|---|---|---|
| Google Cloud / Firebase | Application hosting, authentication, and the Firestore database where all records are stored. | United States (us-central1) |
| Resend | Delivery of transactional email: acceptance links, reminders, one-time verification codes, and notifications. | United States |
| Vercel | Application 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.
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