DRAFT — for legal review, not legal advice

Privacy policy. This page is a draft for legal review. It is not legal advice.

DRAFT — for legal review, not legal advice # Privacy policy DRAFT — for legal review, not legal advice **Website ROI LLC** · Effective date: [effective date] · Contact: [mailing address placeholder] This is a draft for a lawyer to review. It is not legal advice, and it is not in force. Do not publish it, and do not tell customers it is the policy, until counsel approves a version and the date and mailing address above are real. If this text is split across pages, repeat "DRAFT — for legal review, not legal advice" at the top of each page. ## Who we are Website ROI LLC ("we") makes and hosts a CRM for small businesses, and we use that same CRM for our own leads. Two roles sit side by side: - **When a client business uses the CRM for its own customers,** that business decides why the data is collected and what it means. They are the controller. We store and process it for them. We are the processor. - **When we collect data for ourselves** — our own website, our own forms, our own leads, our own account, billing, and how the product is operated — we are the controller. The product is built for businesses. It is not a consumer social network. ## What this draft covers - The CRM application (staff screens, capture forms, booking page, client portal, quotes, invoices, jobs, campaigns, review requests, website scans and the self-serve audit page). - Website ROI's own website, including its first-party analytics and the copy of visit events it may forward into the CRM. A client business that embeds our form on its own site needs its own notice. This draft does not replace that notice. ## Data we collect **CRM records a business puts in, or that a form creates.** Name, company, email addresses, phone numbers (stored in E.164 form), postal address, website, tags, notes, tasks, lead stage and value, quote and invoice line items, job labor and material costs, bookings and intake answers, review ratings and comments, campaign membership, and files the business imports (CSV text is kept with the import job so it can be reviewed or undone). Custom fields the business defines. Consent flags: whether the person agreed to email or to texts, the source of that consent, the time, and the IP address captured with that consent (`consent_ip`). **Capture forms and chat** (`/in/<tenant>/form` and `/in/<tenant>/chat`). Whatever the form sends: name, email, phone, message, page URL, UTM tags, and an optional visitor id. A hidden honeypot field is discarded and, if it is filled, nothing is stored. Marketing email is recorded as opted-in only when the person ticks the box. **Booking page.** Name, phone or email, optional business name and message, the time slot, intake answers, and the same optional marketing tick. **Client portal.** The email address typed to ask for a link. If it matches a contact of that business, we create a single-use link (15 minutes). The session lasts 7 days. We store a hash of the session token, not the raw token, plus an IP address and last-seen time. **Website scans and the self-serve audit.** A URL the business or the visitor asks us to scan, the scores and issues the scanners return, and, if the visitor unlocks a report, their name, email, phone, and a short "where are you today?" answer. Marketing opt-in is only stored when ticked. The scan fetches that website. It is built to refuse localhost, private networks, and similar internal addresses. **First-party analytics on our own site, without cookies.** The site template records, on the server, the page, the channel (paid, email, social, search, referral, or direct), UTM tags, and a visitor id so a later form submit can be tied to the visit. The visitor id is held in the browser's `sessionStorage`, not in a cookie. IP address and user agent are not stored. Do Not Track, Global Privacy Control, and known bots are skipped. Events are forwarded into the CRM only if the site is configured with a CRM URL and ingest secret. That forwarder is off until those are set. **Payment data.** Card numbers are not stored in the CRM. The product does not talk to Stripe yet: checkout is a local stub clearly marked as a test. If Stripe is turned on later, card handling happens at Stripe. We would store invoice amounts, status, and a payment-link id. **Staff accounts.** Name, email, role, and a session cookie described below. **Support and security logs.** Standard server logs (time, path, status). Rate-limit counters store a hash of the key, not the raw IP. Postgres may log queries on the host; treat those logs as sensitive. We do not ask for government id numbers, and we do not want children's data. See "Children". ## Cookies The CRM sets session cookies only. | Cookie | Who | What it is | |---|---|---| | `crm_session` | Staff | HttpOnly, SameSite=Lax, path `/`. Secure when the app runs in production. Lasts 30 days. The value is a signed payload with the user id, the tenant id, and an expiry. It is how staff stay signed in. | | `crm_portal` | A customer in the client portal | HttpOnly, SameSite=Lax, path limited to that business's portal. Secure in production. Lasts 7 days. The database stores a hash of the token. | We do not set advertising cookies, and we do not load third-party analytics scripts. Our own site's analytics, described above, do not use cookies. ## Why we use it - To run the CRM the business asked for: leads, contacts, quotes, invoices, jobs, booking, campaigns, review requests, the portal, and website scans. - To send the messages the product is built to send (portal link, quote or invoice, review request, audit report, campaign to people who opted in). **Today those messages stay on the server's local mail catcher. No outside email provider is connected.** - To keep the service up: sign-in, tenant isolation, rate limits, abuse blocking, backups, and debugging. - To attribute our own site's visits to leads, using the first-party analytics above. - To take payment for an invoice, when a real payment provider is connected. It is not connected. - To meet law that applies to us, once counsel says what that is (tax records, a lawful request). We do not sell personal information. We do not use it for cross-context advertising. We do not train public AI models on customer CRM records. The optional quote-drafting hook (`QUOTE_LLM_ENDPOINT`) is unset. If it is turned on later, this section has to name that provider before it is used. ## Who else touches it Processors below are **placeholders**. No hosting account, email account, Stripe account, error monitor, or backup bucket has been opened for this product. Names get filled in when a contract exists, and this draft gets updated. | Processor | What for | Status | |---|---|---| | [hosting provider placeholder] | The server that runs the app and Postgres | Not bought. Recommended shape is one small VPS. | | [email provider placeholder] | Sending portal links, campaigns, review requests, audit reports | Not connected. The app refuses any mail host that is not localhost. | | Stripe | Card payment for invoices | Not connected. The app accepts test keys only, and none are configured. | | [object storage placeholder] | Encrypted backup copies | Not set up. | | [error monitoring placeholder] | Crash alerts (for example a Sentry free tier, or log alerts) | Not wired. | Client businesses are not our processors. They are the controllers of the records they enter. Their own vendors (their website host, their mailbox) are outside this list. Ingest secrets, session secrets, and database passwords are not shared with those processors except where the host must have them in the server environment to run the app. ## How long we keep it **What the software does today** - Deletes in the app are soft deletes: the row stays, with `deleted_at` set. An import can be undone the same way. This is not erasure. - Staff sessions last 30 days. Portal sessions last 7 days. Portal magic links last 15 minutes and work once. Public audit-report links last 30 days. Review links last 90 days. Quote, invoice, and unsubscribe links last until a staff member revokes them or counsel sets a period. - Rate-limit rows are eligible to be deleted after about a day. - Scan HTML sits on the server disk until someone removes it. - Backups, once the ops scripts are actually scheduled, are 7 daily dumps and 4 weekly dumps. A person who was deleted can remain inside those dumps until the dumps age out (on the order of four weeks for the weekly set). **What the product can do now (this policy is still a draft — counsel reviews it before anyone relies on it)** - The account owner can download one person's data as JSON from that person's page, or download the whole account as a ZIP (one CSV per table, plus a manifest). Ingest secrets and token hashes are left out. The file is generated on the server and downloaded. It is not uploaded anywhere. - The owner can erase one person. Notes, emails, phones, booking answers, portal session details, and review comments are scrubbed. The contact row stays so invoices, quotes, jobs, and payments still point at it, with the name replaced by "Deleted contact". The email address is kept only as a sha256 hash so a later campaign cannot mail it. - The owner can close the account by typing the business slug. The account stays up for 30 days (`pending_deletion`, `delete_after`) and can be cancelled. Export still works during those 30 days. After the date, `npm run data:purge` hard-deletes that tenant. That job is not installed on a schedule in this build. It refuses the agency tenant and it refuses a demo tenant unless forced. - A person who was erased, or whose account was purged, can remain in a backup dump until that dump ages out (7 daily, 4 weekly, once backups are actually scheduled). A request can still be mailed to [mailing address placeholder]. Counsel should set any longer retention that tax or accounting rules require, and should say so here before publication. A placeholder is not a retention schedule. ## Export and delete rights People whose data is in the CRM, and the business that holds the account, can ask for a copy and can ask for deletion. Depending on where they live, that ask may be a legal right (state privacy laws, and GDPR if it applies — counsel confirms). The account owner can do this in the product: Export this person's data, Delete this person, Export everything, and Close account. Those controls exist. This policy is still a draft, and the purge job is not on a schedule until someone installs it on the host. We may ask the client business to handle a request about their customer, because they are the controller. We will help them do it. We may refuse a request the law tells us to refuse, or keep a record the law tells us to keep, and we will say why. Requests: [mailing address placeholder]. Add [privacy email placeholder] before publication so people are not limited to paper mail. ## Security The CRM is built as one database with a row-level wall between businesses: the app role is not a superuser, does not bypass row-level security, and sets the tenant id for the current transaction only. Staff cookies are HttpOnly. Public links are stored as hashes. Rate-limit keys are hashed. Cookie-authenticated writes check the request origin. Scans refuse private and internal addresses. Production responses include HTTPS strict-transport headers (see the launch checklist before preload is relied on). No method is perfect. A backup file is a full copy of the database and must be encrypted off the box. Ingest secrets are plaintext in the database today, protected by that row-level wall; encryption at rest for those secrets is still an open hardening item. ## Children The CRM is for businesses and their adult customers. We do not knowingly collect personal information from children under 13. Do not use the product to store children's data. If you believe we have some, write to [mailing address placeholder]. The account owner can erase that person in the product, and we will help. ## International The server region is not chosen yet: [hosting region placeholder]. Data is stored there, and people who operate the service can access it from where they work. Counsel should add any cross-border terms that apply before this is published. ## Changes We will update this draft as the product gains a host, an email provider, and payments. Export and delete now exist in the product. This page is still not the published policy. The effective date changes when a reviewed version replaces this one. For our own site and leads, we will post the new date on this page. For client businesses, we will tell the account owner before a material change. Counsel should decide how that notice works (email, in-app, or both). ## Contact Website ROI LLC [mailing address placeholder] [privacy email placeholder] DRAFT — for legal review, not legal advice