Exactly what this site collects
I sell governance. It would be absurd to run a site that could not answer the questions I ask other people. So here is the full inventory.
Previously — correction, 17 August 2026.Between 24 July and 17 August 2026 this page was wrong. It said no IP address was retained. In fact every analytics event carried the visitor’s address, and the analytics provider expanded it into an approximate city, postcode and coordinates — including on the events that record starting and completing the diagnostic. The anonymous diagnostic rows in the database were not affected and still carry no address; the analytics record of the same visit did, and this page said it did not.
The cause was a setting that read as a protection. The address was stripped from the request inside the browser, and the receiving service treats an absent address as an instruction to use the one on the connection instead — so stripping it was what published it. It went unnoticed because the fault was invisible in the browser’s network tab, which is where this page invites you to check: the properties were added after the request left. Nothing was sold, shared, or joined to a form submission. The client-side and project-level fixes described in the inventory below are both in place.
Status, 9 September 2026 — open. The removal of the old address and location properties described in the 17 August correction has not been verified against the processor. It is open, not closed. Next review: 9 October 2026. When removal is verified, the completion record and its date will be published here.
The full inventory
Every field this site stores, why, who processes it, and how long it is kept. This table renders src/content/collection-inventory.ts — the same source /engineering renders — so the two pages describe collection once rather than twice.
| What | Why, and when it is recorded | Processor | Retention |
|---|---|---|---|
| Diagnostic scores — four layer scores, sector, jurisdiction, action class, volume band | Recorded when you complete the diagnostic, to build a sector benchmark. No organization name, email, identifier or IP address is stored with the row. | This site's own database (managed Postgres) — table diagnostic_runs. | Kept indefinitely. There is no scheduled deletion job on this table. This row said "24 months" until 9 September 2026; nothing in the code enforced it, and the only automatic deletion anywhere in this database is a 24-hour purge of rate-limit counters. The rows carry no identifier, so there is nothing in them to erase on request — which is why a duration was never built, and not a reason to have published one. |
| Inquiry details — name, email, organization, situation, timeline | Recorded only when you submit the contact form, to respond to you. This is the only place identity is attached, and you attach it deliberately. | This site's own database (managed Postgres) — table inquiries. Forwarded to the practice principal's mailbox so the inquiry can be actioned. | Kept until you ask for erasure. There is no scheduled deletion job on this table — see "One retention rule" on the privacy page for what that means in practice. |
| Subscriber email | Recorded only if you subscribe, to send new writing. | This site's own database (managed Postgres) — table subscribers. | Until you unsubscribe. |
| Diagnostic delivery email — address, sector, overall score band | Recorded only if you ask for the diagnostic PDF by email. Sent with the generated PDF to Resend for delivery, and stored as a contact record so a conversation can follow. Held separately from the anonymous diagnostic row above; the two are never joined. Choosing Print or save as PDF instead sends nothing anywhere. | This site's own database (managed Postgres) — table report_requests — for the contact record; Resend for delivery. | Kept until you ask for erasure in the database. Resend's side is a separate path — see "Email-provider logs" below. |
| Teardown request — name, email, organization, the link or file you send, your notes | Recorded only if you request an asynchronous teardown, to read the artifact and write the critique back to you. | This site's own database (managed Postgres) — table teardown_requests — for the request fields. An uploaded file is forwarded to the practice principal by email and is not retained in the site's storage; only its filename and size are recorded, so the request can be tracked. | Request fields: kept until you ask for erasure. Attachment: not retained here after forwarding — see "Mailbox" and "Email-provider logs" below for where a copy may persist. |
| Anonymous usage events — page viewed, diagnostic started/completed, per-question progress and time bucket, article read depth, time-on-page bucket, page performance numbers, error counts, booking link clicked, form submitted | Recorded as you use the site, to see which pages are useful, where people give up, how far articles are read, how fast pages load, and which article preceded a diagnostic. Configured with memory-only persistence, manual bounded events, no autocapture, no session recording, no person profiles. Every property leaving the browser is a bounded category or a number — no form values, answers, organization names, email addresses, free text, URL, referrer, search term or user-agent string. Durations are reduced to four coarse buckets before capture. See src/lib/analytics.ts for the complete, typed list of events. | PostHog, via this site's first-party proxy. | 12 months. |
| IP address ($ip, attached by the analytics pipeline to every event) | PostHog treats an absent or empty $ip as an instruction to use the address on the connection, so a value has to be sent for the address not to be used. This site sends the fixed placeholder "0" on every event (src/lib/analytics-privacy.ts). A client-side sentinel alone is not the full control: the authoritative one is the PostHog project's own "Discard client IP data" setting, which PostHog documents as the only way to stop the fallback for every ingestion path, including ones this repository does not send events through directly. Both are meant to be in force (docs/posthog-privacy-settings.md). | PostHog. Sentinel applied client-side in src/lib/analytics-privacy.ts; discard setting applied in the PostHog project. | Events captured from 18 August 2026 onward: 12 months, with the other usage events above. Events captured 24 July – 17 August 2026, before the fix, carried a real address and derived location instead of the placeholder: open — see the dated status on the privacy page. |
| Rate-limiting digests — salted SHA-256 hashes derived from the requesting network address and, where a form supplies one, the email address and its domain | Written when a public form or report endpoint is called, to enforce a narrow request limit. Each value is salted and one-way hashed before it reaches storage, so no address, email or domain is recoverable from a counter row. A row holds a digest, a token count and a timestamp — nothing else. These are pseudonymous derived identifiers, used to count repeated requests without storing the original value; they are not a claim that the original cannot be recovered under every threat model. Counters are never joined to form or diagnostic records and are not used to recognize a returning visitor. | This site's own database (managed Postgres) — table rate_limit_buckets. | Deleted once the counter has refilled and can no longer deny anything — at most 24 hours. The only table in this inventory with a code-enforced deletion (src/lib/db.ts). |
| Referrer tag — e.g. utm_source=article | Stored alongside the records above, to know which page led somewhere useful. | This site's own database (managed Postgres), attached to the record it belongs to. | With the record it belongs to. |
| Mailbox — the practice principal's own email inbox | Receives a notification when an inquiry or teardown request is submitted, and carries a forwarded attachment where a teardown request included one. | The practice principal's own email provider — outside this application's database. | Not established in code. Governed by the principal's own mailbox retention, not by this application. |
| Email-provider logs — Resend's own delivery and operational logs | Deliver the diagnostic report PDF and the forwarded notifications above. | Resend. | Resend's own operational email-log retention. Not set by this application. |
| Database backups | Disaster recovery for the application records listed above. | The database hosting provider. | Not established in code. Governed by the hosting provider's backup policy, not by this application. |
Anonymity is scoped, not absolute
“Anonymous” describes the diagnostic-scores row in the database, and it describes that row specifically — not everything you can do with a diagnostic result. The exposures differ by path, and treating them as one thing is how a scoped claim turns into an absolute one:
- The stored benchmark row carries no organization name, email, identifier or IP address, as the inventory above states.
- A shareable link (“Copy shareable link” on the results screen) encodes your full set of diagnostic answers into the URL itself. Anyone who holds that link can decode and read those answers — the link is the access control. Nothing about that URL is anonymous once you send it to someone.
- An emailed report joins your answers to the email address you supplied, as a contact record at the report service, so a conversation can follow. That record is held separately from the anonymous benchmark row and the two are never joined to each other — but the emailed copy itself is, by design, attached to an address.
- An inquiry is deliberately identified: name, email, organization, situation and timeline, because you are asking to be contacted.
One retention rule
Application records that carry an identity you handed over deliberately — inquiries and teardown requests — are kept until you ask for erasure. There is no scheduled job that deletes them on its own; “until the conversation concludes” was never an automatic trigger, and this page no longer implies that it is. Write to vikram@vikramjha.work to have one removed.
That one rule has named exceptions, each with its own trigger, listed in the inventory above and summarized here:
- Mailbox. Submitting an inquiry or teardown request also sends a notification, and any attachment, to the practice principal’s own email inbox. That inbox is not this application’s database; its retention is whatever the principal’s mailbox is configured to keep, not a rule this codebase enforces.
- Attachments. A file uploaded with a teardown request is forwarded by email and is not kept in the site’s own storage afterward — only its filename and size are recorded there, so the request can be tracked.
- Email-provider logs. Resend, which delivers the diagnostic report PDF and the notifications above, keeps its own operational delivery logs on its own retention terms — not ones this application sets.
- Backups. The database host’s backup rotation is not documented in this codebase and is not a rule this application enforces.
The diagnostic-scores row, subscriber email, and the analytics events above each carry their own retention already stated in the inventory, and are not part of this rule — none of them carry the identity this rule is about.
What this site does not do
- No cookies. There is no consent banner because nothing here requires consent. Two things can be written to your device, both in local storage, neither ever read by the server, and both removed by clearing site data. If you use the light/dark toggle, your choice is saved under the key
theme, holding the single wordlightordark, so the page does not flash the wrong palette next time. And a browser of mine that I have marked as my own — so my visits can be excluded from this site’s figures — stores the keyvj_ownerholding the character1. It is set only by opening a link I know, never by anything you do, so on your device it does not exist. That flag replaced the previous way of recognizing my own visits, which was to read the IP address off stored events. - No advertising tags, tracking pixels, session recording, cross-site tracking, or third-party fonts. PostHog is the disclosed analytics processor; the bounded event client is loaded from the first-party proxy and uses the configuration described in the inventory above.
- No real IP address is stored on a usage event: a fixed placeholder is sent in its place and the processor is configured to discard the connection address on arrival — see the IP-address row in the inventory above for exactly what that does and does not cover, including the open item from the incident above. Hosting, network and email providers necessarily process connection metadata in transit under their own security logs and retention terms.
- Nothing is sold, shared or passed to a data broker. Ever.
- The diagnostic works whether or not the storage layer is reachable — the report is computed in your browser.
Rate limiting uses digests, not identities
Rate limiting uses salted digests derived from the address, email or domain, plus bounded counters. These are pseudonymous derived identifiers: they let the site count repeated requests without storing the original value. They are not a claim that the original cannot be recovered under every threat model. The email domain is counted with a deliberately generous allowance: several people from one organization arriving together is expected, not abuse.
Your rights
Under India’s DPDP Act and the GDPR you can ask for access, correction, or erasure of anything identifying you. Since diagnostic rows carry no identifier, the practical scope is inquiries, subscriptions, report requests and teardown requests — the four places you hand something over deliberately. Write to vikram@vikramjha.work and it will be handled within 30 days.
Where it lives
Form, subscription and anonymous diagnostic records live in managed Postgres with transport encryption required by the connection. Operational email is processed by Resend. Usage events are processed by PostHog through the first-party proxy. Access to application records is limited to the practice principal through a token-protected operational view; production-provider access controls remain part of the deployment boundary.
If this page and the site’s behavior ever disagree, the page is the commitment and the behavior is the bug — tell me and I will fix it, and say so here, as above. Most of what is written above is verifiable from your own browser’s network tab in about thirty seconds, and that is rather the point. One honest limit, learned the hard way: the network tab shows what leaves your browser, not what a processor adds after it arrives. That gap is exactly where the August defect lived, so the claims that depend on it — the discarded IP address, the retention period — rest on the processor’s configuration rather than on anything you can see from here.