HonestHook

Sign in

Blog ·

For nine days my terms of service named a company that does not exist

On 17 September I published a terms-of-service page saying HonestHook was operated by Interdemo Tecnologia LTDA, CNPJ 64.006.872/0001-40.

That company does not exist. It has no registration anywhere. The CNPJ beside it is real and it is mine — it belongs to a sole trader, an Empresário Individual, whose registered name is not "Interdemo Tecnologia LTDA" but a string that looks like this: 64.006.872 KAUANE VICENTE PEREIRA. In Brazil a sole trader's legal name is the owner's civil name, prefixed by the CNPJ root. There is no separate company name to invent.

The wrong name sat on a live page, next to a paid-plan checkout, for nine days.

Why nothing caught it

Every automated check I had was looking at the wrong half of the sentence.

The CNPJ was correct. A CNPJ has a checksum, so a validator can tell you the number is well-formed, and mine was — because I copied it from the real registration. The company name next to it has no checksum, no format, no validator. It is free text. Nothing in a build, a test, or a linter has any opinion about it.

Worse, the name was internally consistent across my own systems. Stripe's public business name — the string that appears on the card payment screen — said Interdemo Tecnologia LTDA too, set on the same day for the explicit purpose of matching the terms page. So the two places I would have compared agreed with each other. Consistency between two copies of the same mistake reads exactly like correctness.

The failure mode here is the one this blog keeps returning to: it did not produce an error, it produced a plausible page.

Where the name actually came from

I do not have a good answer, and that is the real finding. The name entered the file on 17 September from a note I had written earlier, not from the registration. I never opened the cartão CNPJ — the one-page registration extract the tax authority serves for free, with no login — to check it.

On 26 September I opened it for an unrelated reason and the razão social did not match what my own site was publishing. Nine days.

The check, if you want to run it on your own site

It takes about forty seconds and it is three greps and one lookup.

  1. Read the registration, not your notes. For a Brazilian CNPJ, solicitacao.servicos.gov.br/cnpj returns the razão social with no login. Whatever your jurisdiction, the rule is the same: the authoritative source is the registry, never the document you wrote about the registry.
  2. Grep your repo for the company name and count the hits. Mine returned seven. One was the published string. Four were dated internal notes, which I left alone — correcting the origin of a fact is not the same as erasing the old mention. Two turned out to be unrelated: business profiles on two abandoned ad accounts, where the same word is a different brand. A blind find-and-replace would have touched all seven.
  3. Check your payment processor separately. The name on the checkout screen is configured in a dashboard, not in code, so it will not appear in any diff. Mine is still wrong as I write this. Fixing the page moved the disagreement rather than closing it.

What the law asks for, at least here

Brazil's Decreto 7.962/2013, art. 2º, I, requires sites used to offer or conclude a consumer contract to display, prominently, the supplier's nome empresarial and registration number. Both, not either.

That rules out two workarounds I considered. Publishing only the CNPJ satisfies the number and not the name. Publishing a trade name — "HonestHook" — is not a nome empresarial, and in my case was not even registered yet. For a sole trader the compliant string is the civil name, which means the fix published my full legal name on a public page. That was the actual decision, and the privacy objection dissolves once you notice that the CNPJ already on the page returns that same name to anyone who looks it up.

What I am not claiming

I am not claiming anyone was harmed. I have no evidence that a single visitor read that page, and I do not know whether anyone relied on it. I am also not claiming I was exposed to a penalty — I did not consult a lawyer about this and I am not one.

What I can state is narrower and, I think, more useful: for nine days my site made a false statement about who it was, on the page whose entire job is to say who it is, and none of my tooling was capable of noticing.

Fixed, and what is still open

The page now reads:

HonestHook is operated by 64.006.872 KAUANE VICENTE PEREIRA, CNPJ 64.006.872/0001-40, an individual entrepreneur (Empresário Individual) registered in Brazil.

Merged and verified in the production HTML, not just in CI, on 27 September.

Still open, and stated rather than quietly carried: the Stripe public business name, which is a dashboard setting and still says the old string; and — found while verifying the fix, at 16:10 on 27 September — the page's own "Last updated" line, which says 16 September. A terms page that was edited today and claims it was last touched eleven days ago is the same class of defect, one layer down. It is in the queue.

Update, 27 September, 19:39 UTC. The "Last updated" line is fixed: the terms page now says 27 September, and the privacy page correctly still says 16 September, because its text did not change. Verified in the production HTML of both pages rather than in the build. One detail worth keeping, because it cost me a wrong conclusion first: React inserts an HTML comment between the literal label and the interpolated value, so grepping the rendered page for Last updated: September 27, 2026 as a single string finds nothing even when the date is right. Grep the value on its own. The Stripe business name is still the old one as I publish this — that one is a dashboard setting, not code.

Trend data with a memory

Every social API answers what’s trending now, then throws it away. HonestHook keeps the hourly archive, so you can ask what gained traction.

Free key, 1,000 credits a month, no card →