How a record is read, kept and checked.
This is the whole method, in the order it runs. It is versioned and dated, so a finding made under one version can be checked against it later.
Method v1.2, in force from 30 September 2026.
1. What is read
Every request a city read makes about a business, and nothing else.
- The domain's public DNS. Its A, AAAA, MX, NS, CAA and TXT records, the TXT record at _dmarc, DKIM keys at 16 common selector names, and its MTA-STS, TLS reporting and BIMI records. One question also goes to Cloudflare's public resolver, to see whether the domain signs its DNS.
- The certificate the domain presents in one TLS handshake on port 443: subject, issuer and expiry.
- The home page, over https:// and over http:// (to see whether a visitor is moved to https://), and once more as a request from another site, to read the headers it answers with. Its response headers and the cookies it sets are read from these.
- Up to six more of its own pages, to find a phone number, a postal address, a contact mailbox and a company number: first the pages the home page links to about contact, about or team, then these common addresses, whether or not the site links them: /contact /contact-us /contactus /contact.html /contact-us.html /about /about-us /aboutus /about.html /team /our-team /staff /people /leadership /locations /location /find-us /get-in-touch /enquiries /reach-us /impressum /legal /imprint.
- Its privacy, terms, cookie and data processing pages, where the home page links them.
- Its robots.txt, sitemap.xml and llms.txt. Whether each is there, and what it says.
- Its careers page, the one the home page links to, or /careers when it links none, and up to two public job boards that page or the home page links to.
- The domain's registration record, from the public RDAP service.
Every page request keeps to robots.txt: a path it closes to Bondstone, or to every crawler, is not fetched. robots.txt itself, the sitemap, llms.txt, the registration record and a job board are asked for directly. Each request says who is asking, and our reader's page says how to stop it. No port is scanned, no file a site keeps private is asked for, no form is submitted, and nothing is logged into.
Every read is one a business's own IT provider could run from any laptop in the office. That is the test for whether something is read: if it needs anything more than this, it is not read.
2. What is kept
For every read: what was asked for, the answer as returned, and the time in UTC. That text is the record.
A finding is a sentence about a record, and it links to the record. A record never links to a finding. If the sentence and the record disagree, the record wins and the finding is withdrawn.
3. What a finding is
A finding is one of this list: the reader's own rules for email, certificates and the web, each with the key it carries in the pack. Each has a plain sentence, the record it is made from, and the fix. Nothing else is a finding, and in particular nothing that would need probing to find.
The email and certificate findings can open a call or a first email. Of the web findings, only a missing redirect to https:// and a cookie browsers throw away can; the rest go on the finding sheet.
| Finding | The record it is made from | The fix |
|---|---|---|
| No SPF record spf_missing | No TXT record at the domain itself beginning v=spf1. | One SPF record for the domain's mail provider, ending ~all: include:spf.protection.outlook.com for Microsoft 365, include:_spf.google.com for Google Workspace. Anything else that sends as the domain goes into the same record. A domain that publishes no mail servers gets v=spf1 -all. |
| SPF lets any server send spf_plus_all | An SPF record whose all term is +all, or a bare all. | The same record with ~all in place of +all, once everything that sends as the domain is named in it. |
| SPF over ten lookups spf_too_many_lookups | An SPF record needing more than ten DNS lookups at its top level (include, a, mx, ptr, exists, redirect). | Take out includes for services no longer used, or replace a and mx with the addresses they stand for. |
| More than one SPF record spf_duplicate | Two or more TXT records at the domain itself beginning v=spf1. | Merge them into one record and delete the others. |
| No DMARC record dmarc_missing | No DMARC record at _dmarc (a provider's verification token there is not one), on a domain that publishes mail servers or whose SPF record names something that sends as it. A domain that takes no email and names no sender is not counted: nobody pays to fix a domain they never mail from. | Publish v=DMARC1; p=none with a reporting address somebody reads, read the reports for 4 to 8 weeks, then move to p=quarantine and then p=reject. |
| DMARC set to monitor only dmarc_monitoring_only | A _dmarc TXT record with p=none. Not when its reports go to a DMARC reporting service: that is somebody's rollout in its monitoring weeks, and it is left alone. | The record the business publishes with one change: p=none becomes p=quarantine (pct=25 only where a pct is already set), keeping where the reports go and every other tag. Where the record sends its reports nowhere, the first step is a reporting address, at p=none. |
| A DMARC record that does not work dmarc_malformed | Two or more TXT records at _dmarc beginning v=DMARC1, one with no p= set to none, quarantine or reject, or a DMARC record receivers do not recognise: stored inside an extra pair of quote marks, or with its tags but no v=DMARC1 first. | Keep one record, with p=none put back where it is missing and every other tag as it is; a record receivers do not recognise is written again the way they read it, the quote marks taken out or v=DMARC1 put first. |
| The wrong record where DMARC belongs dmarc_misplaced | No record at _dmarc begins v=DMARC1, and another mail record is there instead, such as an SPF line put in the wrong place. On a domain that takes no email and names no sender it is not counted. | Replace it with a DMARC record at p=none, with a reporting address somebody reads. |
| Microsoft 365 with no DKIM found m365_no_dkim | Mail servers at Microsoft 365, and neither selector1 nor selector2 answering under _domainkey. Said as "we could not find", because selectors cannot be listed. | Switch DKIM signing on for the domain in the Microsoft Defender portal and publish the two CNAME records it shows. |
| Mail on a web host's mailboxes mail_on_web_host | The primary mail server is a web host's shared mail service (123-reg, IONOS, Fasthosts and the like). Not a fault, and said as a fact. | Nothing is broken today; the usual move is Microsoft 365 or Google Workspace on the business's own domain. |
| Contact address at a broadband provider or a free mailbox contact_on_isp_mailbox | The email address the site publishes is at BT, Virgin Media, TalkTalk, Sky or Plusnet, or a free mailbox such as Hotmail or Gmail, rather than on the business's own domain. | A mailbox on its own domain, with the old address forwarding to it for a while. |
| Certificate lapsing or expired cert_expiring, cert_expired | The certificate presented on port 443 had 14 days or fewer left when it was read, or had already expired. A certificate issued for only a few days at a time counts only once it has expired, and one that ran out more than 90 days before is an abandoned site, not counted. | Renew it with whoever issued it, and get automatic renewal working again. |
| No redirect to https:// no_https_redirect | A request to the http:// address is answered without being moved to https://. | A permanent redirect to https:// on the same host. |
| First redirect not to https:// first_redirect_not_https | The site reaches https:// in the end, but its first redirect goes to another plain http:// address. | Make the first redirect go straight to https:// on the same host. |
| No HTTPS-only header, or one too short hsts_missing, hsts_too_short | No Strict-Transport-Security header on the home page, or one that runs out in under six months. | Strict-Transport-Security: max-age=31536000; includeSubDomains, once HTTPS works on every subdomain. |
| Browsers may guess file types nosniff_missing | No X-Content-Type-Options: nosniff header. | Add that header. |
| Another site may frame the page framing_allowed | Neither X-Frame-Options nor a frame-ancestors policy. | Content-Security-Policy: frame-ancestors 'self'. |
| No content security policy csp_missing | No Content-Security-Policy header, or one that only reports. | A policy sent as Report-Only first, then enforced once its reports have been read. |
| A cookie set without its safety attributes cookie_flags | A cookie set without Secure or HttpOnly, an anti-forgery cookie without SameSite, or SameSite=None without Secure, which browsers throw away. | Set the missing attribute where the cookie is created. |
| Server version announced version_disclosed | The Server or X-Powered-By header names an exact version. | Turn the version off in the server's settings. |
The list changes only with a new version of this method, and the change is dated below.
4. What is removed before ranking
A business that fails any of these is not ranked, is not in any pack, and is not counted toward the hundred.
One rule takes a business out of the emails and not out of the pack. Sole traders and partnerships are individuals under PECR and need consent, so a first email is written only for a business tied to a company registration: a limited company, an LLP or a public body. A business we could tie to none can still be on the call sheet as a number to ring, counted toward the hundred like any other row, and the row says the number could be a sole trader's or a partner's own.
- Anyone on the do-not-contact list, for any channel, from any pack, ever.
- Businesses with no phone number and no contact mailbox to reach them by.
- Any finding read more than 30 days before the pack is built, which stays out of the pack until it has been read again.
5. Receipts
Each record gets one line in receipt.jsonl: the field, where it was read, the read time, the exact text read, and a SHA-256 of that text.
Any SHA-256 tool recomputes a hash from the text in the line, offline, with nothing from us. A pack can be checked years later, on a machine that has never spoken to Bondstone. A script that checks every line at once is not inside the pack; we send it on its own if you ask.
6. Re-verification
A record is re-verified by reading it again and comparing. A finding that fails is replaced two for one.
If a business has fixed the thing since the read, that is not a failure. It is a business that fixed the thing, and the record says when. You will want to know that before you ring, which is why the read date is on every row.
7. Changes to this method
Listed here, with a date, every time.
| Version | Date | Change |
|---|---|---|
| v1.0 | 20 Sep 2026 | First published. |
| v1.1 | 24 Sep 2026 | Written as the reader runs: every request a city read makes is listed, including the common contact addresses asked for whether or not they are linked, and robots.txt, sitemap.xml and llms.txt. The findings are the reader's own list, with an expired certificate and the web findings, and SPF ending in ~all is not one. A certificate is lapsing at 14 days or fewer, a finding read more than 30 days before a pack is built stays out until it is read again, a business with no company registration tied to it gets no email but can be a number to ring, and the receipt's fields and its script are named as they ship. |
| v1.2 | 30 Sep 2026 | A pack no longer carries a script to check its receipts: every hash in receipt.jsonl is SHA-256, which any tool recomputes from the text in the line. |
What we never do
The method above is a list of what is read. This is the list of what is not, for anybody, at any price.
A pack is built from what a business publishes: public DNS, a TLS handshake, its home page and a few of its own public pages, every one listed in the method. No port scan, and no request for a file a site keeps private.
No passwords, no portals, nothing installed, and no account that is not our own.
Reports carry counts only. A business is named only to an IT firm near it, on a private page or in a pack made for that firm, never on a public page.
A sole trader is an individual under PECR and needs consent, so first emails go only to limited companies, LLPs and public bodies. A business we cannot tie to a company can still be a number to ring, and its row says it could be a person's own line.
We promise what we control: the checks, the records and the dates. Nobody honest can promise the rest.
See the method applied to your area
The count is free. The pack is the same method, done for the hundred businesses nearest your office.