privacy policy

Privacy policy

Last updated 2026-08-21 · Effective 2026-05-29

This policy explains what data Backthread collects, why, how long we keep it, who else sees it, and the rights you have over it. We try to write this in plain language. If you read something here and the Security page contradicts it, the Security page is the implementation truth — tell us so we can fix the language.

1. Who's the controller

BACKTHREAD OÜ, registered in the Estonian Commercial Register under number 17524049, with registered office at Harju maakond, Tallinn, Lasnamäe linnaosa, Peterburi tee 92g, 13816, Estonia ("we", "us", "Backthread"), is the data controller for the data described in §2.2, §2.3, §2.4, §2.6, §2.7 and §2.8 below.

For the source code we momentarily clone when you connect a repository (see §2.5), we act as a data processor on your instructions: you decide what code we read and why. The companion Data Processing Addendum sets out our obligations as your processor.

Contact for any privacy question, request, or complaint: hello@backthread.dev.

2. What data we collect and why

2.1 Waitlist signups (controller) — removed 2026-08-20

There is no waitlist any more, and we no longer collect any of this. The form had already been taken off every page; on 2026-08-20 we deleted the endpoint behind it, removed its database and rate-limit bindings, and deleted the notification it sent. Until then it was still reachable, so we are naming it rather than quietly dropping the section.

While it existed, joining the waitlist recorded your email address, which form variant you used, any UTM parameters, your referrer, user-agent and Accept-Language header, the approximate country, city, region, timezone and ISP that Cloudflare reports, and a salted SHA-256 hash of your IP address for rate limiting — never the raw IP. The lawful basis was consent (Art 6(1)(a) GDPR). Sixteen entries were collected in total, between 2026-05-17 and 2026-06-25, and nothing has been collected since. §10 records what happened to them.

2.2 Account data (controller)

When you sign in:

Lawful basis: contract performance (Art 6(1)(b)).

2.3 GitHub installation linkage (controller)

When you connect a repository via the Backthread Ingest GitHub App:

We do not store your GitHub App private key (it lives in our orchestration Worker as a secret) and we do not persist installation access tokens — they are minted per ingest job and destroyed with the sandbox.

Lawful basis: contract performance (Art 6(1)(b)).

2.4 Derived diagrams + changelogs (controller; processor for team customers)

For every connected repository we store:

This is the product. We do not store your source code in this category — only what we derived from it.

Lawful basis: contract performance (Art 6(1)(b)).

2.5 Source code (processor)

When an ingest runs, the orchestration Worker spawns a fresh, isolated sandbox (a Cloudflare Container — Firecracker microVM); inside it we:

  1. clone your repo with git clone --depth 1 using a job-scoped installation token;
  2. read the source statically (no npm install, no require() of your code, no eval);
  3. write only derived data to our database;
  4. destroy the sandbox.

The clone, the installation token, and any in-memory representation of your code die with the sandbox. We do not retain your source code in any database, log, or cache outside the lifetime of that single sandbox. See Security for the implementation detail.

When we process source code, we act as your processor under Article 28 GDPR. See the Data Processing Addendum.

2.6 Operational / transient data

To keep the service running we keep a few short-TTL records:

Lawful basis: legitimate interest (Art 6(1)(f)) — operating and securing the service.

2.7 Page-view analytics (controller)

Both backthread.dev and app.backthread.dev load Cloudflare Web Analytics — a third-party script served from static.cloudflareinsights.com. On app.backthread.dev Cloudflare injects it at the edge, so it does not appear in the source we publish. It did the same here until 2026-08-21, when a change to our deployment configuration switched the injection off without warning; we now carry the tag in our own HTML instead, so on this site it is visible in the source we publish as well as in the raw HTML of any page we serve. Either way, the Security page shows you how to check. Per page view it reports:

The measurements are sent to cloudflareinsights.com/cdn-cgi/rum. Your IP address and user-agent are not collected by the script, but they reach Cloudflare in the HTTP request headers, exactly as they do for every request to any website.

It is cookieless: it writes no cookie, no localStorage entry and no sessionStorage entry, and it mints no identifier that outlives the page load — so it cannot join one visit to the next and cannot follow you to any other site. We use it for exactly one thing: counting how many people reach a page. On app pages the reported path contains the repository slug you are viewing. Cloudflare serves every page of the app, so it already receives those paths when a page is loaded; the script additionally reports paths you reach by navigating inside the app, which the edge would not otherwise see. Either way the recipient is Cloudflare, which is already our host and our sub-processor — the script adds no new recipient, though it does report a little more to that one.

Lawful basis: legitimate interest (Art 6(1)(f)) — knowing whether anyone reads our pages. Article 5(3) of the ePrivacy Directive gates two things: storing information on your device, and gaining access to information already stored there. The script stores nothing, and what it reads is generated by the page load itself rather than retrieved from anything kept on your device, so we treat it as outside the consent gate. We want to be straight that this is our reading, not a settled question — a regulator could fairly press on the second limb, since the script does read your browser's performance and memory figures. If a supervisory authority tells us we are wrong, we will put it behind consent or drop it, and say so here.

Cloudflare injects a second script at the edge, which we also had not noticed until 2026-08-17: Email Address Obfuscation, served from our own origin at /cdn-cgi/scripts/…/email-decode.min.js. It rewrites mailto: links and bare addresses into a /cdn-cgi/l/email-protection link and decodes them in your browser, so that address scrapers do not harvest our inboxes. It collects nothing, sends nothing, and stores nothing. Its side-effect was on you, not us: with JavaScript disabled, the address you need in order to exercise any of the rights in §7 did not render at all. Since 2026-08-21 every address on this policy, the DPA, the Terms and the Security page is excluded from the obfuscator and is served as an ordinary mailto: link that works with JavaScript switched off. The obfuscator still runs elsewhere on the site. Addresses are additionally written out in plain text in the imprint at the foot of the Security page.

Those two are the complete set of scripts we serve anywhere, as of the date at the top of this policy — but they are no longer both on every page. Since 2026-08-21 the obfuscator is injected only where an address still needs obfuscating, and none are left on this policy, the DPA, the Terms or the Security page, so those four load the analytics beacon alone. Listing every <script> tag in any response we serve is still the check to run: expect one on the legal pages, and on the home page that one plus the obfuscator plus a short inline script of our own that loads nothing and contacts nobody — three tags, two of them third-party. We will not add another without naming it here first.

2.8 Billing data (controller)

If you subscribe, payment is handled by Stripe — through Stripe Checkout and the Stripe billing portal. Stripe collects your card details directly; they never reach our servers and we never see or store a card number. What we keep is the subscription state Stripe reports back to us: your Stripe customer and subscription identifiers, plan, seat count, status, and invoice history.

Lawful basis: contract performance (Art 6(1)(b)), and compliance with our accounting obligations (Art 6(1)(c)) for the invoice records.

2.9 Lesson answers and grades (processor for team customers)

If you use the lessons, we keep the free-text answer you typed, the grader's verdict on it, and the grader's note. The answer is sent to Google to be graded; your identity is not sent with it (see §5 and §11). The account-scoped deletion that applies to a lesson answer is described on the Security page.

Lawful basis: contract performance (Art 6(1)(b)) — providing the product your account signed up for. For a team account we process these as processor on the account owner's instructions under the DPA.

3. What we do not collect or do

4. How long we keep things

DataRetention
Source code in the ingest sandboxDestroyed at end of job (job timeout ≤ 10 minutes)
Derived diagrams + changelogs + flows + decisionsUntil you disconnect AND explicitly ask us to delete (we keep derived data after a disconnect so you can reconnect without losing history; you can ask for deletion any time)
Account dataUntil account deletion (self-serve from /account or via email)
GitHub installation linkageUntil you uninstall the GitHub App AND ask us to delete the linkage row
Waitlist signupsDeleted 2026-08-20 — the waitlist was removed and the entries with it (§2.1, §10)
Per-IP rate-limit hashes10 minutes
Webhook delivery / queue-dedupe markers10 minutes
Operational logs (worker tier)≤ 30 days at Cloudflare
Lesson answers, verdicts + grader notes (§2.9)Until the person leaves the account, or the account is deleted, or you ask us to delete them
Billing records — subscription state + invoices (§2.8)Held by Stripe as well as us; we keep invoice records for as long as Estonian accounting law requires (7 years), even after account deletion
Page-view analytics events (§2.7)Held by Cloudflare, not by us — we store none of it ourselves and cannot lengthen or shorten their retention. Per Cloudflare's documentation: unsampled for 7 days, then aggregated for longer-term storage, with roughly the previous six months visible to us

Where we delete data, we delete it; where the rule requires us to retain it (e.g. accounting records for tax purposes), we keep what the rule requires for as long as it requires.

5. Who else sees it (sub-processors + recipients)

We use the following sub-processors — providers that process data on our behalf. Each operates under a Data Processing Agreement. With Google and Anthropic those are the providers' own published standard terms, linked in the table, rather than agreements we negotiated line by line — and we want to be exact about what that does and does not mean, because we used to be vague about it. Each of those addenda takes effect by being incorporated by reference into the commercial terms we accepted when we opened the account: no separate signature is required for either addendum to bind. Both providers do offer an acceptance step — Google's addendum refers to a partner having “clicked to accept”, and Anthropic's own help page is titled “how do I view and sign” — so “unsigned” is not quite the right word either; what is accurate is that neither addendum waits on a negotiation or a countersignature from us. Whether that is as good as a bespoke agreement is a judgement we are not going to make for you in our own privacy policy; what we can do is name the exact instrument and link it, which the table does. What differs between providers is the transfer mechanism, so the table names each one specifically instead of claiming Standard Contractual Clauses across the board. Separately, Cloudflare's page-view analytics (§2.7) appears in this table for completeness even though we run it as controller, not on any customer's behalf — the DPA §6 explains why it is not a sub-processing activity. Recipients that are not sub-processors are listed separately after the table.

ProviderRoleWhat they seeWhere
Supabase, Inc. Database, auth, realtime Account data, derived diagrams, derived changelogs, flows, decisions and their risk items, and lesson answers + grades (§2.9) EU region (eu-west-1, Ireland). DPA · Trust Center
Cloudflare, Inc. Pages, Workers, Queues, KV, D1, and cookieless page-view analytics (§2.7) Worker job buffer, transient dedupe / rate-limit data, and page-view analytics events (path, host, referrer, user-agent, load timings) Global edge, with the EU jurisdiction option for our D1 bucket. DPA · Sub-processors
Google LLC LLM naming + narration of the diagram, decision derivation over redacted capture transcripts, and writing + grading the lesson questions in the app Diagram enrichment: module + file identifiers, edge metadata, PR titles + bodies. Decision derivation: redacted capture transcripts (natural-language only; no source code, no tool I/O). Lessons: the recorded decision a question is written from, and — when grading — the answer you typed. Your identity is never sent with it US. Google is our processor under its Data Processing Addendum for Products Where Google is a Data Processor (Google's own service list is what puts “Gemini API Paid Services” in its scope), which the Gemini API terms incorporate by reference. It covers paid Gemini API use specifically. Our project runs far past the free tier's daily limit, so paid is the only way our usage could be served — but that is our reading of our own bills, not something we can show you from this page, and we would rather flag it than let it pass as settled: if it were ever wrong, this addendum would not apply and Google's unpaid terms permit training on what is sent. For transfers it applies a Data Transfer Solution where one exists (the EU–US Data Privacy Framework) and Standard Contractual Clauses where one does not.
Anthropic Ireland, Limited (its Commercial Terms name this entity for customers in the EEA; Anthropic, PBC elsewhere) LLM tie-break for decision derivation from redacted capture transcripts Redacted capture transcripts (natural-language only; no source code, no tool I/O) US processing. Anthropic's DPA, incorporating EU Standard Contractual Clauses (Module 2 and/or Module 3, to the extent applicable data protection law requires), is automatically incorporated into its Commercial Terms of Service — accepting those accepts the DPA, with nothing to sign. DPA
GitHub, Inc. OAuth identity + the read-only GitHub App Your GitHub identity + the source code you grant the App to read US. EU SCCs under the GitHub Data Protection Agreement.
Stripe Payments + subscription management (§2.8) Your billing name, email, address and card details — collected by Stripe directly, never by us. Nothing from your repositories Contracting entity and region are set out in the DPA linked here — for EU customers Stripe contracts through its Irish entity. EU SCCs under the Stripe DPA. DPA · Privacy Center
Resend Delivering the emails we send you — the Decision Digest and trial notices Your email address and the contents of the email, which for the digest includes decision titles + summaries derived from your repository US, per the DPA linked here. EU SCCs under the Resend DPA. DPA

We push internal operational alerts into five private Telegram channels — errors, signups, product, marketing and ops — and one of our own internal tools also posts a nudge into Telegram. We name the operator as Telegram FZ-LLC, which is the Dubai group company; Telegram's own policy names Telegram Messenger Inc. as the controller. We have not confirmed which entity we contract with, and we would rather say that than pick one and sound certain. This section used to say that was one direct message about a new waitlist email, and that Telegram never saw customer data. Both were wrong — and the waitlist itself is now gone (§2.1), so that message is no longer sent at all. Rather than give you a count of messages we cannot verify, here is every kind of thing that goes there, read out of the code that sends it:

We are not going to tell you how many messages there were, and you should know why. We do not keep the messages we send. Some of these paths leave a record of the failure that triggered them, but that record is written whether or not the message actually went — and messages are de-duplicated before sending, so even the records that exist do not map one-to-one onto anything Telegram received. Three earlier drafts of this section carried a precise message count. Each was wrong, in a different way, because it was counted from something that was not the thing being counted. What we can stand behind, and have named above, is that particular repositories were named and roughly when — read from the repositories and their build failures, not from a tally of messages. Even that is a floor rather than a total: some repo-naming alerts (a stalled capture, a frozen decision log) write no record at all, so there may have been more.

What never reaches it: your source code, your captured transcripts, and the text of a lesson answer. The dispute alert above carries the note's length, never its words — though that was not true before 2026-08-19, and §10 says what changed.

We treat Telegram as a recipient, not a sub-processor, because it is a messaging channel we push notifications into under its own terms rather than a service processing your data on our behalf to deliver the product. That label does not shrink what it receives, and it operates under no Data Processing Agreement with us — we would rather write that down than let the word "recipient" imply a protection that is not there. If you'd rather we didn't notify the founder about your signup, tell us at hello@backthread.dev and we'll turn it off for you.

Two answers in the FAQ on our home page can play videos from YouTube (Google), through the youtube-nocookie.com privacy-enhanced player. Each one shows a play button, not a player: the embed is not in the page until you press it, so your browser sends nothing to Google unless you choose to watch. Once you do, Google receives that request and with it your IP address and user-agent, and whatever the player then stores in your browser is Google's behaviour, not ours — we will not characterise it on their behalf. We treat Google as a recipient here rather than a sub-processor, because this is our page, not your data. You can also skip the embed entirely: the timestamped links beside each player open the same moment on YouTube.

We should say why this is worded so carefully. Until 2026-08-17 both videos were ordinary embeds marked loading="lazy", and this policy said your browser therefore contacted YouTube only if you scrolled to them. We measured it, and that was false — browsers do not defer iframes the way they defer images, so both players were fetched on every home-page load, more than six thousand pixels below the fold, one of them inside a collapsed answer. Every visitor's IP address went to Google. We rebuilt them as click-to-load rather than write the exposure down and leave it in place.

Apart from the two Cloudflare scripts in §2.7 and those two video embeds, the pages on backthread.dev request nothing from a third party: fonts are served from our own origin, and there are no external images and no tag manager. Every other external address on those pages is an ordinary link that loads only if you click it. The signed-in app at app.backthread.dev necessarily talks to more: our own ingest worker, Supabase, and — only when you open billing — Stripe.

We will publish at least 30 days' notice on this page before adding a new sub-processor that processes customer data. (Telegram is intentionally not in this list because it is a recipient rather than a sub-processor — not because what it receives is trivial. That is set out above.)

6. International transfers

We are established in Estonia; our primary data store (Supabase) is in the EU (eu-west-1, Ireland).

Some sub-processors are US-headquartered (Cloudflare, Google, Anthropic, GitHub, Stripe and Resend — Anthropic contracts through Anthropic Ireland, Limited and Stripe through its Irish entity for EU customers, as §5 says). For those transfers we rely on the European Commission's Standard Contractual Clauses (SCCs, Commission Implementing Decision 2021/914) incorporated into each sub-processor's DPA — with one exception we should not bury: Google's processor terms apply a Data Transfer Solution (the EU–US Data Privacy Framework) where one is available and fall back to SCCs only where it is not, so for Google the mechanism may be the Framework rather than the Clauses. §5 names it per provider. All of it is supplemented by the supplementary measures described on Security — the most important of which is that we never persist your source code, which sharply limits what a US authority can compel about it.

One transfer is not covered by that: the internal alerts we push to Telegram (§5), which is outside the EEA and has no Data Processing Agreement with us and therefore no SCCs. We are naming it here rather than letting the paragraph above read as if it covered everything.

A summary Transfer Impact Assessment is available on request to hello@backthread.dev.

7. Your rights

Under the GDPR + the Estonian Personal Data Protection Act (PDPA, 2018) you have the right to:

To exercise any of these rights, email hello@backthread.dev. We'll respond within one month, per Art 12(3); if your request is complex we may extend by two months and tell you why. We do not charge for handling a request unless it is manifestly unfounded or excessive.

8. Security

We describe what we do — and what we don't do — on the Security page. Highlights: TLS in transit; encryption at rest by our cloud providers; ephemeral sandboxes for source code; least-privilege GitHub App scope; secrets only inside the worker tier; safety budgets against pathological inputs.

If you think you've found a security issue, write to security@backthread.dev (or hello@backthread.dev) and we'll respond within one business day. We do not yet run a bug bounty.

9. Children

Backthread is for adults. If we learn we've collected data from a child under 16 without parental authority, we'll delete it.

10. Changes

We'll update this page when we change a load-bearing fact and bump the date at the top. For material changes affecting your rights, we'll email the address on your account at least 14 days before the change takes effect.

2026-08-21 — we said every sub-processor has a DPA without having checked which one, and we had the wrong country on the page that says where your data lives. §5 asserted that each sub-processor operates under a Data Processing Agreement "relying on EU Standard Contractual Clauses where data leaves the EU." We went and read the actual instruments. Three things were wrong. One: we linked the wrong agreement for Google. We cited the Google Cloud Data Processing Addendum; we do not use Google Cloud or Vertex AI, we use the Gemini API, and its terms name a different document — the Data Processing Addendum for Products Where Google is a Data Processor. The Cloud addendum does not list our service anywhere. Two: Google's transfer mechanism is not simply "EU SCCs" — that addendum applies a Data Transfer Solution such as the EU–US Data Privacy Framework where one exists, and falls back to Standard Contractual Clauses where it does not. Anthropic's genuinely is SCCs, Modules 2 and 3. Three: Anthropic's own Commercial Terms say that for a customer in the EEA the contracting entity is Anthropic Ireland, Limited, not Anthropic, PBC. We are in Estonia. We had named the wrong company. And separately, this policy, the DPA and the Security page all said our database sits in eu-central-1, Frankfurt. It sits in eu-west-1, Ireland. Both are in the EU and no data moved — but we had told you the wrong country, and we would rather correct it than let it stand because it looked harmless. On the underlying question — whether a published addendum nobody countersigned is really our agreement — §5 now states the mechanism (incorporation by reference into commercial terms we accepted) and links the instrument, instead of hedging in one document and worrying in another. The Cloudflare row also no longer lists lander signups, which stopped existing when we deleted the waitlist.

2026-08-21 — the address you need in order to use §7 did not render without JavaScript. Cloudflare's Email Address Obfuscation rewrote every address on these pages into a link that only a script could decode, so a reader with JavaScript switched off saw "[email protected]" where our contact address should have been — including in §1 and §7, which is where a data subject is told how to reach us. §2.7 had disclosed the script since 2026-08-17 but treated the consequence as an inconvenience to us. It was not: it made the contact route the law requires unusable for anyone browsing that way. Every address on this policy, the DPA, the Terms and the Security page is now excluded from the obfuscator and served as a plain mailto: link. We kept the obfuscator running on the rest of the site rather than switching it off in a dashboard, because a setting no file in our repository records is not something we can promise you about — the exclusion lives in the pages themselves, and a check in our deploy script fetches the published pages afterwards to confirm a working address is really there.

2026-08-21 — three corrections to what we published yesterday. Yesterday's Telegram correction, below, was checked again — this time against the deployed code rather than the copy of the source we happened to have — and three things did not survive. One: the Security page told you that a connected repository which never builds is never named to Telegram. That is false, and §5 on this page already said so: failure alerts name a repository precisely when its build goes wrong, so a repository that never builds successfully is named the first time it fails. The Security page now matches. Two: §5 said one of our internal tools sends its nudge to the founder's direct message. We could not verify that — the destination is a deployed secret, and the last time we described one of those from the name in the code we published something false — so we have removed the claim rather than repeat the mistake. The nudge still goes to Telegram, and it still carries no data about you. Three: §5 and the Security page said Telegram never receives your source code. We have stopped writing never there. We do not send it your code, but a failure alert carries a tail of the error output from a tool that was reading your code, and we cannot rule out that a line of it appears in one. A sentence in §5 that an earlier edit had left garbled has also been repaired.

2026-08-20 — we removed the waitlist and deleted what it had collected. The sign-up form had already been taken off every page, but the endpoint behind it was still live and still accepting email addresses that nothing on the site linked to. We deleted it, removed its database and rate-limit bindings, deleted the Telegram notification it sent, and deleted the credentials it used. Sixteen entries had been collected between 2026-05-17 and 2026-06-25; all sixteen have been deleted, and §2.1 and §4 now say so. The lawful basis for holding them was your consent to join a waitlist, and there is no waitlist to join, so continuing to hold them was not something we could justify. If you gave us an email address that way, we no longer have it.

2026-08-20 — a correction, and an admission: we understated what Telegram receives, and until 2026-08-19 it received more than this. §5 and the Security page both said the founder gets one Telegram message when a new email joins the waitlist, and that Telegram never sees customer data. Both halves were wrong. It goes to five private Telegram channels — errors, signups, product, marketing and ops — plus a nudge our own marketing tooling posts when it has work waiting. They receive the email address and GitHub username on each app signup other than our own test fixtures; product and failure alerts carrying repository names — including private repositories belonging to our customers; service alerts carrying counts about customers and Stripe identifiers; account, installation and user identifiers; and our daily marketing sweep, weekly engineering and production-health summaries and monthly strategy review. §5 sets out each kind in full. It deliberately gives no counts: we do not keep the messages we send, and three earlier drafts of that section each published a precise number that turned out to have been counted from something that was not the thing being counted.

The part that is not merely a disclosure fix. Until 2026-08-19, disputing a graded answer sent Telegram up to 300 characters of the note you typed and 200 characters of the question — the exact text the Security page says is readable only by you. We changed the code that day so the alert carries the question's identifier, the verdict and the note's length only, and we verified the deployed worker no longer contains the old text. So "never the words" is true now, and it was not true before 2026-08-19. We are stating that rather than letting the present tense cover it. One thing we can tell you, as far as our records go: not one of the lesson answers we currently hold has ever been disputed — so on that evidence the words in question were never actually sent. We say "as far as our records go" precisely: answers are deleted when an account is deleted or a person leaves a team, so the rows we hold today cannot prove what happened to rows we no longer have. The defect was real; the exposure, on the record we have, was not. We are reporting both halves, because reporting only the reassuring one is how the original sentence went wrong.

Nothing about what we store or how long we keep it changed, and no new sending started. Telegram remains a recipient rather than a sub-processor, and §5 now says it operates under no Data Processing Agreement with us, because the label was doing work the facts did not support. That has a consequence we should not leave for a reader to find: Telegram is outside the EEA, so this is a transfer with no Standard Contractual Clauses behind it. §6 and the DPA describe SCC coverage for our sub-processors, and we have added a sentence to each saying plainly that this recipient is not one of them. Narrowing what we send there is tracked as work, not as a claim.

2026-08-19 — a removal, named rather than made quietly. §2.9 used to say that who can see a lesson answer was described on the Security page. We removed that pointer, because we removed the paragraph it pointed at. Both said, in different words, that a person's coverage is visible to nobody but them. That stopped being true on 2026-08-12, when we decided a team's lead can see an individual's coverage, and it shipped shortly after. Nothing about what we store or how long we keep it changed, and the deletion rules still apply and are still on /security. What changed is that we no longer make a promise the product does not keep. The lesson answers we store, their verdicts and the grader notes remain readable only by you. Three actions publish what you typed, on purpose, and all three are yours to take: recording an answer as a decision, disagreeing with something we recorded, and flagging a question as bad. Telling us a grade was wrong is not one of them — that note stays on your own answer row, readable only by you. On a public repository a recorded answer is readable by anyone, and so is a disagreement filed against a decision; a disagreement filed against a graph anomaly stays with account members, and the kill record is never public. A recorded answer can also reach teammates in the daily digest email.

2026-08-17 — a correction. §3 claimed we used no third-party analytics. That was false the whole time it was published: every page on both of our domains, this one included, was serving Cloudflare's cookieless page-view script. Cloudflare injects it at the edge, so it appeared in no file we publish and repeated reads of our own source could not find it — we found it by reading a live response. Rather than quietly soften the sentence, we are naming what happened. In the same pass we added §2.7 describing precisely what that script reports, named the role in §5, disclosed the two YouTube embeds on our home page as a recipient, and added Google's lesson question-writing and grading role to §5 and §11 — it was described on the Security page but missing from this one and from the DPA.

Auditing that correction turned up three more things, all fixed on the same date, and all worth naming rather than absorbing quietly:

11. AI Act transparency

The Backthread product uses a general-purpose AI model (Google Gemini) to name and narrate the modules + per-module changelog you see in the diagram. The diagram structure is derived deterministically from your source code; the model never authors it. Strings the model produced are tagged in the UI so you can question them. This disclosure is provided in advance of the Article 50 EU AI Act transparency-obligation deadline (2 December 2026 per the May 2026 Commission consultation).

The same model also writes and grades the lesson questions in the app: it drafts a question from a decision already recorded in your repository, and when you answer, your typed answer is sent to be graded and a verdict plus a short note comes back. Your identity is not sent with it. A grade is a model's judgement, not a fact about you — the app shows you the grader's note precisely so you can disagree with it.


BACKTHREAD OÜ · registration number 17524049 · registered office Harju maakond, Tallinn, Lasnamäe linnaosa, Peterburi tee 92g, 13816, Estonia · hello@backthread.dev