Draft. Not reviewed by a lawyer. Do not show this to a customer.
This was written by the engineer who built the software, by reading the code. It has not been reviewed by anybody qualified to review it. It is published here so that it can be read, checked and corrected — not so that it can be relied on. Nothing in it is an offer, a contract or legal advice, and it must not be linked from a signup flow or signed by anybody until a lawyer has read it.
All three documents · 17 unfilled markers in this document
Privacy Policy
Draft — not reviewed by a lawyer
This document was drafted by the engineer who built the software, by reading the database models and the code that writes to them. It has not been reviewed by a lawyer. It must not be put in front of a customer, linked from a signup flow, or relied on by anybody until a qualified person has read it. Every [NEEDS ZACH: ...] marker below is a fact only Zach can supply, and a marker that is still showing means this document is unfinished.
It is written to be true about this specific application rather than generic. If you change what the software collects, this document is wrong until somebody changes it too.
1. Who we are
[NEEDS ZACH: the legal entity name, exactly as registered], of [NEEDS ZACH: the registered business address], operates the business development platform described here ("the Platform").
For anything in this document that needs a reply from us, write to [NEEDS ZACH: the contact address for data requests — a mailbox somebody actually reads, which may or may not be the same one as the legal notices address in the Terms of Service].
2. Two very different sets of people
Almost every privacy policy describes one relationship: the company and its users. This Platform has two, and conflating them would make this document useless.
Our customers' staff. The restoration company's owner, managers and sales reps. They have accounts, they sign in, they chose to be here. For their personal data we are the controller of the account itself (their sign-in address, their password, their sign-in history) and the processor of everything they do with it.
Everybody else in the database. Facilities managers, property managers, hospital and hotel and university staff, networking-group members, and the owners of commercial buildings. These people did not sign up, have usually never heard of us, and are in the system because one of our customers is trying to win their business. We hold their data only on our customers' instructions. Our customer is the controller; we are the processor. Where the law gives those people rights, the obligation to answer sits with the customer who holds the record, and we help them do it.
[NEEDS ZACH: the lawyer needs to confirm this split, and in particular who owes the notice duty to a prospect whose details were collected from public map data without their knowledge. This is the single biggest legal question the product raises and it is not a question an engineer should answer.]
3. What the Platform actually holds
Written from the database, table by table, grouped by whose data it is.
About a customer's staff
- Account: email address, name, role, whether the account is active, and the company it belongs to.
- Password: never stored. What is stored is a PBKDF2-SHA256 hash with 600,000 iterations and a per-password salt. We cannot read your password and we cannot recover it, only reset it.
- Sign-in history: every sign-in attempt, successful or not, with the address used, the source IP address and the time. This is what makes the lockout work and what answers "who signed in from where".
- Password reset requests: a one-time hash of the reset link, its expiry, whether it was used, and the IP address that asked for it.
- Writing voice: the openers, closers, sign-off, banned phrases and length preferences the Platform learns when a user pastes in three to five of their own sample emails. The sample emails themselves are not kept; the profile learned from them is.
About the people our customers are selling to
- Contacts: name, job title, company, email address, phone number, the kind of contact they are, their status in the pipeline, when they were last contacted and when they are next due, how many emails have been sent to them, whether we believe the address is reachable, free-text notes typed by a rep, and which rep owns the relationship.
- Accounts (companies): name, property type, street address, city, state, postal code, phone, website, an employee-count band, year established, whether they own or rent the building, and notes.
- Jobs: a property address, a loss type (water, fire, mould and so on), a status, an estimated value, and a link to a contact.
- Activity: notes and logged interactions against a contact, with who logged them and when.
- Draft and sent messages: the full subject and body of every message written to a named person, why it was generated, who approved it, when it was sent, and whether they replied. This is the most sensitive table in the Platform. It is the actual text of commercial messages written to named individuals, and it is retained as described in section 6.
- Tags applied to contacts.
- Networking groups: which groups a contact belongs to, their role in each, and a ledger of referrals given to and received from them with an estimated value on each. This amounts to a record of a commercial relationship between two named people.
- Scraped properties: commercial buildings found in OpenStreetMap — name, type, address, phone, website, coordinates — held on a review page until somebody decides whether to import them. A facilities-manager name and email field exists on this table and is empty on every record today, because the step that would fill it is not built (section 9).
- Imported files: when a customer imports a CSV, the raw contents of every row are stored while the import is reviewed, and kept afterwards so there is a record of what was about to happen.
About events in the world
- Weather and fire events: alert headlines, descriptions, severity, areas, towns, start and end times, and source links, taken from the United States National Weather Service and from news feeds the customer configures. These describe places and incidents, not people, although a news headline about a fire can name a business.
About how the Platform was used
- Audit trail: an append-only record of every action worth answering for later — sign-ins, failures, lockouts, password changes, role changes, every draft written, approved, rejected or sent, every import and export, every pause, every deletion and restore. Each row carries who did it (the account id and the email address), what it was, when, and the source IP address. Payloads are scrubbed on the way in so that anything whose field name looks like a password, token, secret, key, cookie or credential is replaced with
[redacted]before it is written. - Agent runs: when each scheduled job ran, what it found, what it created and why it declined.
4. What we do not hold, and do not do
These are all true of the software as it stands, which is why they are worth stating rather than being left to inference.
- No payment card data. There is no billing system in the Platform at all yet. When there is, card details will be handled by the payment provider and will not reach our database.
- No analytics, no advertising, no trackers, no third-party scripts. There is not one external script, stylesheet, font or image anywhere in the Platform. Nothing about your use of it is reported to anybody.
- One cookie. A session cookie, so the Platform knows you are signed in. It is HttpOnly, it is
SameSite=Lax, it is marked Secure when served over HTTPS, it expires after twelve hours, and there is deliberately no "remember me" cookie, because a long-lived credential on a phone left in a van is not a trade worth making. There are no other cookies and no use of browser local storage. - No tracking pixels in outgoing mail. The Platform does not insert one, so it does not know whether a recipient opened a message.
- We do not sell data, we do not share one customer's data with another, and we do not use customer data to train a model.
- No location tracking. Every browser capability the Platform does not need — camera, microphone, geolocation, bluetooth and eighteen others — is switched off by a policy header on every response.
5. Who can see it
Inside a customer's company. Every record belongs to exactly one company, and every read is filtered by that company's identifier at a single chokepoint in the code. A request for another company's record is answered "not found" rather than "not allowed", because confirming that a record exists is itself a disclosure. Within a company: a manager or owner sees the whole company's data; a sales rep sees the contacts they own and the drafts they wrote, and not their colleagues'. A colleague's IP address is visible to managers only.
Us. A small number of platform administrators can see across all companies. This is real and it should be stated plainly rather than buried: the administrator screens list every company, their user counts and record counts, and the audit log across all companies. It exists so that a support call can be answered and a fault investigated. Every administrator action is itself written to the audit trail.
[NEEDS ZACH: how many people will have platform administrator access, and whether you want a written internal rule about when it may be used. A lawyer will ask, and a buyer with an IT department will definitely ask.]
Sub-processors. The third parties that necessarily touch customer data in order for the Platform to run.
| Sub-processor | What they do | What of yours they hold |
|---|---|---|
| Railway | Hosts the application and the PostgreSQL database | Everything in the Platform |
| [NEEDS ZACH: transactional email provider — Postmark or similar, not yet chosen] | Would deliver password resets and the weekly report | Staff email addresses and report contents |
| [NEEDS ZACH: payment provider — Stripe, account not yet created] | Would take payment | Billing contact and payment details |
| [NEEDS ZACH: contact-enrichment provider, not yet chosen] | Would find a facilities manager's name and email | Property records sent for lookup |
The last three are listed because they are planned, not because they exist. Today the only sub-processor is Railway.
Services the Platform reads from, which receive no personal data. The Platform fetches from three kinds of outside source, and it is worth being precise about what travels outbound, because "we use a third-party API" is usually left ambiguous:
- The National Weather Service (
api.weather.gov) receives a state code or a weather-zone list. No contact data. - The OpenStreetMap Overpass API receives a geographic bounding box. No contact data.
- News feeds the customer configures receive an ordinary HTTP request for the feed. No contact data. Feed addresses are validated so that they cannot point at an internal network address.
Disclosure required by law. If we are compelled to hand over data we will do so, and we will tell the affected customer unless we are prohibited from telling them. [NEEDS ZACH: confirm with the lawyer whether a commitment to notify is one you can safely make.]
6. How long it is kept
This section describes retention controls that actually run, not an intention.
Deleted records go to a bin for 30 days. Deleting a contact, a job, a company account, a group or a draft marks it deleted and takes it out of every screen, every list and every export immediately. It is recoverable from the bin for 30 days, and a countdown on the bin screen says how long is left. The window is one constant in the code (SOFT_DELETE_WINDOW_DAYS in app/models.py), currently 30 days: long enough that somebody notices a mistake after a holiday, short enough that a former customer's data is not sitting around indefinitely.
After 30 days they are really deleted. A scheduled job removes expired records permanently. When a contact is removed, the things written about that contact go with them: every draft and sent message written to them, their tags, their networking-group memberships, and their referral records. That last one moves a networking group's referral balance, and that is the honest outcome — a balance attributed to somebody the customer asked us to forget would be worse.
The audit trail survives it. The record that a message was sent to somebody remains; the text of the message does not. The audit trail is append-only and nothing in the Platform updates or deletes a row in it.
[NEEDS ZACH: how long may the audit trail keep a person's email address and IP address? Today the answer is "for ever", because nothing prunes it. That is defensible as a security and accountability record and it is exactly the kind of "for ever" a regulator asks about. The lawyer should give a number, and then I will build the pruning job. The same question applies to the sign-in attempt log, which keeps an email address and an IP address per attempt and is also never pruned.]
Backups. Backups are retained for 14 days, with the three most recent always kept even if they are older than that, so that a corruption introduced on a Friday is still recoverable the following week. The consequence, stated rather than hidden: a record that has been deleted and purged can still exist inside a backup for up to a further 14 days. The retention numbers live in app/backup.py so that this paragraph can be checked against the code.
When a customer leaves. Their records are deleted on the schedule above. [NEEDS ZACH: how long after an account closes should the data be deleted rather than merely deletable — immediately, 30 days, 90? And should a customer be able to ask for an immediate wipe? A lawyer will want a number here, and whatever it is, I will build it.]
7. Where it is kept, and how it is protected
The application and the database run on Railway. [NEEDS ZACH: which region the Railway project is in, because that determines whether data leaves the country the customer is in, and therefore whether international transfer language is needed at all.]
What the software does to protect it, specifically:
- Traffic is served over HTTPS. In staging and production the Platform sends a Strict-Transport-Security header, so a browser that has visited once refuses to connect over plain HTTP for a year.
- Passwords are hashed with PBKDF2-SHA256 at 600,000 iterations and are never stored or logged in a readable form.
- Repeated failed sign-ins lock an address, and separately lock a source IP address at a much higher threshold, so neither grinding one account nor spraying one guess across many addresses works. The counters are in the database rather than in process memory, because several application workers run at once.
- Every state-changing request carries a one-time token tied to the session, so another website cannot make a signed-in browser act on your account.
- A Content-Security-Policy on every response allows scripts and styles only from the Platform itself and forbids inline script entirely, so a malicious string typed into a contact's name cannot execute in a colleague's browser.
- Sessions expire after twelve hours. Switching off a user's account ends their open session on their next request rather than at their next sign-in.
- Audit payloads are scrubbed of anything that looks like a credential before they are written.
- Backups are written with owner-only file permissions and are verified by restoring them into a scratch database and checking the restored rows, not by checking that the backup command succeeded.
[NEEDS ZACH: whether the Railway PostgreSQL volume is encrypted at rest, and whether Railway will provide that in writing. Do not let the lawyer write "encrypted at rest" into a contract until the host has confirmed it.]
8. Rights, and how to use them
If you are a customer's member of staff and want to see, correct or delete your account data, ask the owner or administrator of your own company first — they can do most of it from inside the Platform. If they cannot, write to us at the address in section 1.
If you are somebody a customer of ours has in their system — a facilities manager who received an email, say — the company that contacted you is the one holding your details, and they are the ones who can remove you. If you write to us instead, we will pass your request to the customer concerned and tell you that we have, within [NEEDS ZACH: a number of business days. A lawyer will know what the applicable law requires; pick the shortest one you can actually meet.]
If you want to stop receiving messages, say so in a reply to the message. Reaching a person at the company that sent it is faster than reaching us, because they have the record and the stop switch.
[NEEDS ZACH: which privacy laws you are accepting that you fall under. That decides what rights have to be listed and in what words — the California rights, the GDPR rights, both, or neither. It depends on where you sell and to whom, and it is not a judgment an engineer should make.]
9. Automated processing, stated plainly
The Platform makes two kinds of automated judgment about people, and both deserve naming rather than hiding in a feature list.
Lead scrubbing scores a prospect on the size and age of their business, whether they own or rent their building, whether a decision maker has been verified and whether a trigger event matched. A low score holds the prospect back from the outreach queue, so the score does decide whether a particular person receives a commercial message. A human can override it, and the override is recorded.
The retention engine decides who is due a touchpoint, from the calendar, from a storm or fire landing on a town where they have a building, from a job anniversary, or from how long they have been quiet.
In both cases the output is a draft that waits for a person. Nothing is sent automatically unless the customer has deliberately switched automatic sending on for a specific campaign.
[NEEDS ZACH: ask the lawyer whether scoring a business contact for commercial outreach counts as automated decision-making that needs a disclosure or an opt-out under any law you sell into. My reading is that it does not, because the effect is "receives a sales email or does not". That is a reading, not advice.]
10. Things the Platform cannot do yet, so that nothing here is read as a promise
Named because a privacy policy that describes features that do not exist is exactly as misleading as one that hides features that do.
- The Platform does not send email as itself. There is no transactional email provider connected, so password reset links are produced on screen by an administrator rather than emailed, and the weekly management report is shown on a dashboard rather than delivered.
- The Platform does not yet send mail through a customer's own mailbox. Microsoft 365 and Gmail connections are not built. Approved messages are held in a sandbox and are not delivered to anybody.
- The Platform cannot find a contact's email address. The enrichment step that would look one up is a stub, so every scraped property arrives with no email address and the review screen says so.
- No large language model sees customer data. Drafts are generated locally from the user's own voice profile and a template, with no network call. If that changes, the model provider becomes a sub-processor and this document changes first.
11. Changes
If we change what the Platform collects, this document changes with it. We will tell customers before a change that affects them. [NEEDS ZACH: how much notice, and by what means, given that there is no email delivery yet.]
Last revised 8 October 2026. This is a draft. It has not been reviewed by a lawyer.