Skip to content
Privacy

What this app does with your information

This page has two halves and they are not the same kind of writing. The description of what the software stores, sends and shows to third parties is exact, and it was read out of the source rather than assembled from a template. The parts a privacy policy needs that only the operator and a lawyer can supply are missing, and each one is marked where it belongs.

Caution: No lawyer has read this page

It is accurate about the software and it is incomplete as a policy. The boxes headed “Not drafted” below are the gaps, and they are the reason this page is not yet fit to be the privacy policy linked from an App Store or Google Play listing. docs/GO_LIVE.md carries the same item: have a lawyer read the terms of use and the privacy policy.

One thing that claim does not cover, said plainly because “accurate about the software” excludes it only by implication. This page names the Personal Information Protection and Electronic Documents Act and in several places describes what it requires or what rights it gives you. Nobody who wrote those sentences has read the Act, and nothing has been checked against it. They are one person’s understanding rather than the law, and every one of them is part of what counsel is being asked to review.

Who this is

Nested is built and operated by Quotograph Inc. Where that company is incorporated is not recorded anywhere in this repository, so it is not stated here, and nor is a business address. This page refers throughout to the Personal Information Protection and Electronic Documents Act, PIPEDA. Nobody who wrote this page has read that Act, and whether it is the legislation that governs this product, whether provincial legislation applies alongside it, and what either requires of the operator are questions for counsel rather than answers this page can give.

This is a pre-release build. There is no account, no sign in, no card field and nothing in it that can charge you, which is the fact most of the rest of this page follows from: there is no payment record of you here, because there is no payment code here at all.

That is not the same as saying nobody pays us, and the difference is worth a sentence rather than an implication. Trades pay to receive quote requests, on one of four plans, and we take a referral fee from some advisors when an introduction leads to a transaction, which the card of each advisor it applies to says on its face. Neither arrangement takes anything from you or collects anything about you, nothing has been charged under either, and the terms of use set both out in full, including what the code does and does not let payment influence.

Caution: Not drafted: the accountable individual and how to reach them

Two of the three things this clause would carry do not exist anywhere in this repository: nobody is named as accountable for privacy compliance, and there is no business address. Neither is invented here. The third does exist, and it is a route rather than a clause: the operator’s own email address is published on the support page and printed on this website’s error screens, so a privacy question has somewhere to go today. Whether an address on its own answers what the Personal Information Protection and Electronic Documents Act asks of an organisation here is a question for counsel. Nobody who wrote this page has read that Act.

This box is not the clause. It is a note recording that the clause is missing. Supplied by: Quotograph Inc..

There is no account, so there is no profile of you

There is no sign in, no sign up and no password of your own. Nothing on any server holds a record of who you are, because there is nothing that could tell one reader from another. The shared password some deployments of this build sit behind is a curtain in front of an unreleased product, not an account: one password, handed to a handful of people, that identifies nobody.

What follows from that is worth stating in both directions, because a page that only said the first half would be selling privacy rather than describing a storage decision. Nobody can read what this app has kept on your device, including us, and there is no server-side store of it to be breached or subpoenaed. It also means none of it is backed up, none of it follows you to another phone or browser, and clearing your browser data removes it with no way to get it back. The one thing that claim does not cover is a form you have filled in and sent, which is a different act with a different answer, and the two sections after this one are about that.

Your file lists every key in the table below as it stands on this device, what is currently in each one, what deleting it costs you, and a control that deletes it.

What the website stores on your device

All of it is written by your own browser, into this site’s local storage or session storage, and none of it is transmitted anywhere by the act of being stored. There are 12 keys and this is the complete list:

  • nested.buyerFile.v1local storage

    Your four welcome answers and everything you have typed into your file: the range, the down payment available, must-haves, the questions you want answered, the areas, your timing, and a record of the requests you have sent.

  • nested.favourites.v1local storage

    The listings you hearted, as a list of listing references.

  • nested.shelf.v1local storage

    One observation per saved listing: the price, which price that was, the status, and the date it was written down.

  • nested.savedSearches.v1local storage

    Each search you named, as the address that reproduces it, with the date you saved it.

  • nested.recentSearches.v1local storage

    The last six things you typed into the search box or the command palette, and the map point of any that had one.

  • nested.journey.v1local storage

    Which tasks you have ticked on the closing checklist, and the closing date you set.

  • nested.possession.v1local storage

    For each property, the tasks you have ticked on the plan for after the deal goes firm, and that property's closing date.

  • nested.onboarding.v1local storage

    That the introduction has been seen on this device, which panel you left it on, and whether you skipped it.

  • nested.themelocal storage

    Light, dark, or follow the system.

  • nested.map.v1local storage

    Whether the map re-runs the search as you pan, and how much of the map the card sheet is allowed to cover.

  • nested.search.densitylocal storage

    Whether search results are drawn as cards or as rows.

  • nested.search.scroll:session storage

    How far down a set of search results you had scrolled, one entry per set of filters.

Three of those hold something a reader should notice specifically. nested.buyerFile.v1 is the closest thing here to a financial picture of you: a budget range, the down payment you have available, whether you are pre-approved, your timing, and a record of the requests you have sent. nested.recentSearches.v1 is search history, being the last six things you typed and the map point of any that had one. And nested.savedSearches.v1 keeps each named search as the address that reproduces it, so the filters you chose are in it.

One footnote about older devices, because the alternative is a list that is quietly wrong. An earlier build stored five notification preferences inside nested.buyerFile.v1. Nothing read them and the field was removed. Reading the key ignores fields it does not recognise rather than rewriting it, so a browser that used that build still holds the leftover object until the next time the file is saved, at which point it is dropped.

There is no other client-side storage. No IndexedDB, no Cache Storage, no service worker, and nothing in the product reads or writes a cookie.

The one cookie, and it is temporary

This build sets exactly one cookie, named homestead_preview, and only on a deployment that is behind the shared preview password, and only after somebody types that password correctly. It exists to remember that they did.

Its value is a version marker, the time it was issued, and a signature over those computed with the password itself. That is the whole payload. There is no identifier in it, no reader in it and nothing derived from you in it, because one shared password means one anonymous audience and a subject claim would imply the gate can tell two people apart, which it cannot. It is marked httpOnly, so no script on the page can read it, SameSite=Lax, and Secure on any production deployment. It lasts seven days, enforced by the signature rather than by the expiry attribute a browser would let you edit.

It is not an analytics cookie, it is not shared with anyone, and it disappears from the product entirely when the password is removed before public launch. Clearing your cookies removes it. Nothing else in this app is a cookie.

What leaves your device, and what happens to it

Some of what you type reaches this server as you type it, with no button in between, and that is worth stating first, because a reader told the opposite will type an income into a calculator on the understanding that the figure stays with them. The affordability panel sends your income, your down payment and the monthly debt payments you entered about a quarter of a second after you stop typing, and it has no button on it that sends, because typing is what sends. The lender comparison sends the same figures along with the credit band you picked, the employment type and the past bankruptcy or consumer proposal box if you tick it. The offer tool puts your income, your down payment, your debts and the ceiling you said you would not go above into the address of a request. The search box sends what you have typed once it is two characters long. The saved screen and the command palette send the identifiers of the listings you shortlisted. The plan for after a deal goes firm sends your closing date. Moving a slider on any of the cost sheets sends the figures behind it and gets the arithmetic back.

A form is the other way information leaves, and there the rule holds as stated: it leaves when you press a button on a form you have read, and what is sent is the fields that were on that form. Six forms in this build carry a name, an email address and sometimes a phone number: a quote request to a trade, an inspection booking, an insurance quote request, an advisor introduction, a viewing request and a trade’s application to join the network.

What happens next is less than the forms imply, and this is the part a template policy would get wrong in the direction that flatters us. Nothing submitted through any of those forms is written to a database. The only database this build uses holds synced MLS listings and has no table that a submission could reach. The only file this server writes is the listing snapshot.

  • A viewing request is validated, echoed back to you and discarded. Nothing is delivered and the response says draft rather than sent, because nothing left the process. On the website the draft is recorded only into your own file on your own device.
  • An insurance quote request, including the prior claims you describe, is turned into a summary and handed back to you. There is no send path in that route at all. The web form then offers you a mail link so that you are the one who mails it, from your own mail client.
  • An advisor introduction composes the text of the introduction and returns it to you. There is no mail transport for it and the advisor records in this build carry no email address or phone number to send to. Your shortlist is included only if you tick the box that says so, which starts unticked.
  • A trade’s application to join is pushed onto a list in the memory of the one server process that received it, and vanishes when that process does. The response tells the applicant exactly that.
  • A quote request to a trade and an inspection booking are the only two that reach an email path. On a deployment that has email configured, part of that path sends and part of it refuses, and which part is which is set out in the next section. Read it: it is the one place in this build where what you typed leaves for a third party.

What every one of those requests does is compute and reply: affordability, a mortgage calculation, closing costs, an offer strategy, a cost sheet, your checklist progress. Not one of them is written to a database, to a file, or to any list that outlives the answer, because there is no table in this build a figure you typed could reach. Two things the server does hold briefly are worth naming rather than hiding inside that sentence. The text you type in the search box becomes a cache key in the memory of one server process, kept for an hour for the typeahead and for a day for a full address you search, so that a free geocoding service is not asked the same question twice. And every request is counted against a key derived from your IP address for the length of a short rate limiting window, which the section below on analytics describes. The mobile app posts checklist progress rather than putting it in a URL, so it does not end up in a request log.

Who else sees anything

This is the complete list, and for the browser it is enforced rather than promised: the Content Security Policy in this app’s Next configuration names every origin the page is permitted to contact, so a request to anywhere else fails rather than happening quietly.

The map, which is what your device contacts a third party for. Map tiles are fetched by your browser, or by the mobile app, from a tile server, and a tile request necessarily carries your IP address and the tiles you asked for, which is the part of the map you are looking at. There are three answers to which server that is and no fourth. With no key configured the tiles come from CARTO’s free basemaps; with a MapTiler key set they come from MapTiler instead; and an operator can point the app at a map style of their own, in which case the tiles come from whatever host that style names. Your browser is held to exactly that: the Content Security Policy permits those two hosts and the one an operator configures, and a tile request to any other provider fails rather than happening quietly. The same three-way choice exists in the mobile app, which has no such policy in front of it.

The font server the map labels are drawn from. On the keyless CARTO basemap, which is the default, every label the website draws on the map, meaning the price pins and the cluster counts, is drawn from glyph files your browser fetches from the OpenMapTiles font server. That request carries your IP address in exactly the way a tile request does, which is why it is named here beside the tile server rather than left as an implementation detail. It is written into the map style this app builds rather than into a setting, so an operator running the default basemap cannot switch it off, and switching it off would only leave the labels blank. Where a MapTiler key or a style of the operator’s own is configured, the lettering comes from that style instead and this host is not contacted at all. The mobile app never contacts it: its tiles arrive with their lettering already drawn on them.

Listing photographs, where the two clients differ. The seed listings in this build use photographs served from Unsplash. On the website your browser asks this site’s own image optimizer and this server fetches the photograph, so what reaches Unsplash is a request from the deployment rather than from you. In the mobile app the device fetches the photograph itself, so there your IP address does reach them. The mobile app also caches listing photos on the device through a standard image caching library, which writes them to the app’s own cache area.

Geocoding, points of interest and rates go through this server, not your browser. The search box’s suggestions come from Photon, forward geocoding from Nominatim, nearby amenities from Overpass, interest rates from the Bank of Canada’s Valet API, and civic datasets from the City of Toronto’s open data portal. All five are called from this server. So the text you typed reaches Photon, and a set of coordinates reaches Overpass, but your IP address does not: the address those services see is this deployment’s. The volunteer-run OpenStreetMap services also require a contact address in the request, and it is never yours. It is whatever address the deployment sets in HOMESTEAD_CONTACT_EMAIL. A production deployment that has not set it does not send those requests at all, rather than sending them with an invented address: the features that depend on those three services come back empty instead, which is a smaller loss than putting a fictional contact in front of somebody who runs a server as a volunteer. Either way the address in that request is not a contact route this page can offer you. The route this build does have is the address on the support page, which reaches the operator and is the same address this website prints when a page fails, and the accountable individual clause above is still the one that owes you a named person behind it.

The hosting provider. Whoever hosts this app receives every request you make to it and can log it the way any web server logs a request. The deployment documented in docs/DEPLOY.md, and the one this repository carries a cron configuration for, is Vercel; the same document describes a self-hosted container as the alternative, so the answer depends on which is running. This app writes no access log of its own. When a request fails it writes one line, and that line carries a request id, the method, the path, the status and the error message. Nothing else is in it: not the body of the request, not a header, not your IP address, and not the query string, because the path is read from the pathname alone and everything after the question mark is dropped before the line is written. Three other lines exist in this server and are named here rather than covered by a sweeping claim: a warning that the contact address for the volunteer-run services above is unset, an error when an idle database connection dies, and a warning that this deployment cannot read back the listings it syncs. Each is a fixed sentence about the server’s own configuration or its database, and none of them carries anything you typed or anything that identifies you.

Email, which is off until two variables are set. The one outbound email path in this build sends through Resend, and it is used for a quote request to a trade and an inspection booking. It requires two environment variables, and with either absent nothing is attempted at all: no request reaches the provider and the response reports the delivery as not configured rather than as sent.

On a deployment that has both, half of that path is blocked and half of it is not, and the difference is worth setting out rather than summarising. Every trade and inspector in this build is a seeded record with an invented address, and the code refuses to mail a seeded record under any configuration, with no environment flag to override it. So the fan-out to trades sends nothing today, and that half is genuinely shut.

The confirmation copy addressed to you is a second, separate send, and there is no provenance check on it at all. It goes out. It is addressed to the email address you typed, it opens with your name, and for an inspection booking its body is the same scope that was written for the inspector, which begins with the property’s full street address and ends with your access notes word for word. Those four things, your name, your email address, that street address and those notes, reach Resend on such a deployment, seeded directory or not. For a quote request to a trade the body carries your description of the job and the municipality rather than a street address.

Your phone number is the one item on those forms that does not leave today, and the reason is not a decision to hold it back. It is written only into the message addressed to the trade, which is the message the seed guard stops, so it stays behind as a consequence of that guard rather than as a promise this page can make. When the directory stops being seeded, that message starts sending and the phone number goes with it, along with your name, your email and the job you described. Your address is set as the reply address on it, so a trade replying reaches you directly. There is also an optional setting that blind copies the operator on each message to a trade.

The MLS feed, which sends data to this app and receives none. Real listings would arrive from PropTx’s syndication service for the Toronto Regional Real Estate Board. That is a one-way read performed by this server on a schedule: nothing about you is sent to PropTx or to the board, and no search you run reaches them. As of this writing there is no feed connected at all, because the credential depends on a brokerage agreement that has not been executed, so every listing in the product is seeded and labelled as seeded.

Fonts are not a third party here. The two typefaces are downloaded at build time and served from this site, so displaying a page makes no request to a font host.

There is no analytics and no tracking, and that is checkable

No analytics product, no telemetry, no crash reporting, no session replay, no advertising or attribution SDK, and no A/B testing service is installed in either the website or the mobile app. Not as a direct dependency and not underneath one. The website loads no third-party script of any kind. There is no tag manager, no pixel and no tracking identifier. Nobody is building a profile of your behaviour here, because there is nothing installed that could.

Two things exist that a careful reader should not be told are nothing. There is an error reporting hook in the code with no destination attached to it, so it discards what it is given. And requests are rate limited by IP address, which means an address is held in the memory of one server instance for the length of a short window and then evicted. It is not written to a log and not stored anywhere.

The mobile app declares one permission, which is network access, and asks you for nothing at run time. There is no prompt for location, camera, photo library, contacts or the microphone, because it uses none of them. It never reads the GPS, and it contains no app tracking transparency prompt because there is no tracking in it to ask about. Its map opens on a fixed point in downtown Toronto and says on screen that this is a default location rather than yours.

What the mobile app stores on your phone

The app keeps five things in the phone’s own preference store, on the device, and nothing else. Each has a control in the app that clears it, and uninstalling the app removes all of it.

  • homestead.favourites, the listings you saved.
  • homestead.journey.progress, your stage in the buying process, which tasks you have ticked, any notes you typed against a task, and your target closing date.
  • homestead.possession.progress, the same kind of checklist for after a deal goes firm, kept per property.
  • homestead.mapNotes, areas you drew on the map by hand, as lists of coordinates with the date drawn. These are never transmitted.
  • homestead.recentSearches, the last eight searches you typed.

Two of those are sent in the body of a request when the app needs the server to recompute a plan from them: your journey progress, including the notes, and your post-firm checklist. Both endpoints calculate and reply without storing anything. Favourites, map notes and recent searches are never sent. Listing photographs are cached on the device by the image library the app uses, which writes them into the app’s cache area.

Children

This product is about buying residential property in Ontario. It is not directed at children, there is nothing in it designed for or likely to appeal to a child, and it carries no content aimed at anyone under the age of majority. It also collects no age and has no account, so it cannot tell who is using it and does not attempt to.

Caution: Not drafted: the age statement each store's questionnaire asks for

Apple’s age rating and Google Play’s Data safety and target audience declarations are answered in each store’s console, not on this page, and the answers are a representation by the operator. The paragraph above describes the product accurately and is not a substitute for filling those in.

This box is not the clause. It is a note recording that the clause is missing. Supplied by: Quotograph Inc., before submission.

Your rights under PIPEDA, and what they reach here

One line before the next paragraph, in the same spirit as the boxes below. What follows is how the author of this page understands those rights. It was not read out of a file the way the rest of this page was, nobody here has read the Act, and it is the first thing on the list counsel is being asked to check.

PIPEDA gives you the right to ask an organisation whether it holds personal information about you, to be told what it holds and what it has been used for and disclosed to, to get access to it, and to have it corrected if it is wrong. It also gives you the right to complain, and to escalate a complaint to the Office of the Privacy Commissioner of Canada, which oversees the Act.

What is worth saying plainly is where those rights land on a product shaped like this one. Everything described in the two device sections above is already in your hands and not in ours: an access request could not return it, because it was never sent, and a correction or deletion request is a control in the app rather than a letter to anybody. The profile page lists every key with a delete button, and the mobile app has a clear control for each of its five.

The information an access request could reach is therefore whatever you have actually sent, which today means an email that left through the configured provider if one is configured, and the operator’s own copy of it. That is the operator’s inbox and account rather than anything in this software, and the next box is why this page stops here.

Caution: Not drafted: how to make an access, correction or deletion request, and the complaint route

What is missing is the procedure: nobody is named to address a request to, there is no statement of what a requester would be asked to provide, no response time anybody has committed to, and no description of how a complaint is handled or escalated. None of that is visible in the code and none of it is guessed at here. Until it is written, a request sent to the address on the support page reaches the operator directly, which is what that page tells you. That is a working route and it is not the procedure this box stands in for.

This box is not the clause. It is a note recording that the clause is missing. Supplied by: Quotograph Inc. and its counsel.

What a finished policy still needs

These are the remaining clauses. They are listed together rather than scattered through the page because they are one piece of work for one person, and because a reader deserves to see the size of the gap in one place.

Caution: Not drafted: consent

What a reader is taken to have consented to, when, how consent is withdrawn and what withdrawing it does. Consent language has legal effect and is not something to draft from a reading of the source. Note for whoever writes it: the forms in this build show the payload before it is sent, and the advisor form’s shortlist checkbox starts unticked, so there is real opt-in behaviour in the code to describe rather than invent.

This box is not the clause. It is a note recording that the clause is missing. Supplied by: counsel.

Caution: Not drafted: retention and disposal

How long the operator keeps an enquiry once it arrives, and how it is disposed of. No period is stated here because none is verifiable from this repository: the software stores nothing, so every real retention question is about an inbox and a third-party email account whose settings are not in the code.

This box is not the clause. It is a note recording that the clause is missing. Supplied by: Quotograph Inc..

Caution: Not drafted: security safeguards

PIPEDA requires safeguards appropriate to the sensitivity of the information and a description of them. What the code can support is narrow and specific: HTTPS in transit, one signed httpOnly cookie, secrets held in server-side environment variables only, and no server-side store of submissions. Everything beyond that is about how the company runs, which is not visible from here.

This box is not the clause. It is a note recording that the clause is missing. Supplied by: Quotograph Inc..

Caution: Not drafted: processing outside Canada

The hosting provider, the email provider and the tile provider are third parties, and where each processes data is set in their consoles rather than in this repository. PIPEDA expects a reader to be told when their information may be processed in another country and may therefore be reachable by that country’s courts. Confirm the regions, then write it.

This box is not the clause. It is a note recording that the clause is missing. Supplied by: Quotograph Inc. and its counsel.

Caution: Not drafted: breach notification

What the operator undertakes to do if there is a breach of security safeguards, which PIPEDA makes reportable where it creates a real risk of significant harm.

This box is not the clause. It is a note recording that the clause is missing. Supplied by: counsel.

Caution: Not drafted: an effective date and how changes are notified

App store review expects a dated policy. This page carries no date, because a date on an undrafted policy is the part that makes it look finished.

This box is not the clause. It is a note recording that the clause is missing. Supplied by: Quotograph Inc..

Changes to this page

This page is edited when the software changes, and the factual half of it is meant to be checked against the code rather than trusted. If a statement here disagrees with what the product does, that is a defect worth reporting, and it is the code that is the evidence.

The terms of use cover the other half of the same honesty: what this build is, that the listings are seeded, who pays us, and what its figures are not good enough to be used for. Its section on what is stored, what is sent and where is the fuller account of the paragraphs above about typing: it works through the panels on this website that send what you type without a button one at a time. If either page is edited, read the other.