← All privacy impact assessments
PIA: Search and suggested times on the phone
Status: Implemented and reviewed locally — not released. Written before the code, and revised against it on 30 September 2026. No model is used: the phone compares spellings, not meanings, with a method called letter-triple matching (§1). Written: 30 September 2026 · Last revised: 12 October 2026 Nothing here is legal advice. Children's Code citations are to the exposure draft; section numbers may move on registration (due 10 December 2026).
As built, 30 September 2026. Event time suggestions and meal search now run entirely on the phone, and a Phones-only group's task search does too, matching this design with no deviation we found. This has been built and merged but not released: it reaches a phone only with the app update that follows our next release, and until then every search and suggestion described here runs exactly as it does today, through our server.
A task's time of day, suggested from the group's own past tasks (assessed before code on 12 October 2026, and built against this addendum the same day, with no deviation we found; not released): §9's trigger asks for this assessment to be revised before what the phone compares is widened, and the task sheet is about to compare tasks the way the new-event form already compares events. It reads the group's own task rows the phone is already holding open — no new read, no model file, no request, and nothing typed leaves the phone — and compares spellings by the same letter-triple method under the same checks set out below, including the one that suggests nothing when the closest past task names a different person. A task whose words are sealed with a key this phone does not hold is left out rather than compared as the placeholder word. A time is offered only where at least three similar past tasks agree within half an hour, and then only as one chip reading "like last time" beside the choices already there: nothing is filled in, nothing is pre-selected, and no time reaches a saved task unless the member taps it. The comparison is worked out again each time the sheet opens and kept nowhere in between, and because nothing leaves the phone it works the same for every group and every account. The suggestion adds no record of its own; whether to go further and suggest how far ahead a task is usually due waits on the counts the event suggestions already produce, of how often a suggested time was kept and how often it was changed.
1. Purpose and scope
Three features compare a few words a member types against the group's own records. Until this change, all three did the comparison on a server:
- Suggested times. Typing "Dinner" into a new event fills in 6:30 pm for an hour, because that is when the group's dinners usually are. When the title was not an exact match for a past event, the typed title and up to 150 of the group's recent event titles were sent to our assistant server and compared, in Sydney, by an embedding model.
- Task search. Pressing Search sends the query and up to 150 of the group's task titles and notes to the same server and the same kind of model, in Sydney. Device-only groups were refused it.
- Meal search. Pressing Search in the meal library sent the query to a function on our database's servers, which sent it to a model provider outside Australia.
What changes, in one sentence each:
- Suggested times are worked out on the phone. What is typed is not sent anywhere.
- Meal search is worked out on the phone. What is typed is not sent anywhere.
- Task search is unchanged for groups at the Australia and Global levels. In a Device-only group, pressing Search now finds tasks with a similar spelling on the phone, instead of saying search is not available.
How the phone compares. Each text is cut into overlapping three-letter pieces ("dinner" gives "din", "inn", "nne", …) and two texts are as alike as the share of pieces they have in common. This catches the mistakes people actually make when they retype a title — "Tenis lesson", "Kindy pick up", "Ada footy trg" — and does not understand meaning: "Evening meal" does not find "Dinner". It needs no model file and no download. For suggested times it is wrapped in three checks (§5) that refuse the kinds of wrong suggestion the plain method made.
Why this method. We tested two small sentence-embedding models against it before choosing (§3.1). Neither was good enough to justify the 51–60 MB they would add to the installed app, and for suggested times the letter-triples were better. A second, separately written test then checked the guarded version against the server method it replaces, by a rule written down beforehand (§3.2).
In scope: what leaves the phone in each feature after the change, what the phone keeps, who can use each feature, and what still has to happen before the old server versions are switched off. Out of scope, covered elsewhere: sealing task and event titles (a later change); the privacy levels themselves; the search screens' design; the server task search, which keeps its own assessment (semantic task search).
2. Data involved
| Kind | Whose | Children's? | Sensitive? | Free text? |
|---|---|---|---|---|
| The title or query a member types | the member's own words | possibly — "Ada dentist" | possibly — health errands are ordinary titles | yes |
| The group's recent past timed events (title, start time, length) — the 300 most recent, read to the phone | the group's, written by any member | often | possibly | yes (titles) |
| The group's tasks already on the phone (title and notes), for a Device-only group's search | the group's | often | possibly | yes |
| The meal plans the member's group can see, and the names of their recipes | ours, published — and a group's own custom plans | no | no | a custom plan's description |
| A count of how each suggestion turned out: which kind of match answered, whether the time was kept, changed or never used, and how long the look-up took | nobody's in particular — no title, no member | no | no | no |
Not collected, and these absences carry the design:
- No typed title or query leaves the phone for suggested times or meal search, or for a Device-only group's task search.
- Nothing new is stored on the phone that outlives the screen. The past events and recipe names are held while the form or the meal library is open and are gone when it closes.
- No model file, no vectors. Nothing is downloaded and there is no numerical representation of anybody's titles anywhere.
Why each item is strictly necessary (s 38(2)(b)): the typed words are the question; the past events are the only place a suggested time can come from; the tasks and the plans are what is being searched. None of it is new collection — every row is one the member can already read on their phone.
3. Flows and locations
| Data | Device | Supabase (Sydney, ap-southeast-2) | GCP (australia-southeast1) | Model provider | Region |
|---|---|---|---|---|---|
| Typed title for a suggested time | compared on the phone | — | — | — | the phone |
| The group's 300 most recent past timed events | read to the phone once per new-event form, compared there | read through the member's own access, as the calendar already does | — | — | Sydney → the phone |
| Meal search query | compared on the phone against the plans already loaded | — | — | — | the phone |
| Recipe names for the plans in the library | read to the phone on the first search, by plan | read through the member's own access | — | — | Sydney → the phone |
| Task search query, Device-only group | compared on the phone against the tasks already there | — | — | — | the phone |
| Task search query, Australia and Global | unchanged — see semantic task search | ||||
| Suggestion outcome counts | — | one row per saved event where a look-up ran: group, stage, outcome, milliseconds | — | — | Sydney |
What still leaves the phone, stated in full:
- The read of past events. The phone asks our database for the group's 300 most recent past timed events, filtered by the group, the kind of event and the current time — never by anything typed. It is an ordinary read of rows the member can already see, through their own access, and it tells our database that somebody opened the new-event form, which the saved event a moment later reveals anyway. A title sealed with the group's key is opened on the phone with the key it holds; a row this phone cannot open is left out rather than compared as the word "Encrypted".
- The read of recipe names. The first meal search on a screen reads the recipe names of the plans shown, by the plans' own identifiers. It tells our database that meal search was used; it does not carry the query.
- The outcome counts. One row per saved event where a look-up ran: which kind of match answered (the same title, a similar spelling, or none), whether the suggestion was kept, changed or overridden, and how long the look-up took. No title and no member identity; it is deleted with the group. Our privacy policy names it.
Sealed titles. Because the comparison runs where the key is, a sealed title can be compared without being unsealed anywhere else. This is why these features had to move before more titles are sealed: a server comparison cannot work on a title it cannot read.
Old app versions. A phone that has not updated keeps the old behaviour — the server comparison for suggested times and meal search — until it does. Those server functions stay switched on until no supported app version needs them.
3.1 The first evaluation: no model
We wrote the decision rule down before running anything, then tested it on hand-written cases — four invented groups with 88 past events and 108 typed titles, 60 invented tasks with 28 searches, and 30 searches over the public meal catalogue. Nothing in the tests came from a real group. A model would be chosen only if it made clearly fewer costly mistakes on suggested times than the no-model option, counting a wrong suggestion three times as heavily as a missing one.
Neither model met that. The letter-triples got 74.5% of the held-out cases right against 46–49% for the models. The models' strength was refusing cases that should be refused — "Kit footy training" when only Ada's is in the calendar — and the plain letter-triples wrongly suggested a time in 8 of 55 cases, mostly another person's activity or a title starting "No". For search the models found more of the right results (91–93% of wanted tasks in the first five, against 64%), because searches ask about meaning.
3.2 The second evaluation: the guarded method against today's server method
We then added the three checks in §5, fixed every setting on the cases already seen, and wrote down — before running it — the rule for shipping: the guarded method replaces the server's suggested times only if, on a fresh set of cases, it makes no more costly mistakes than the server method, wrongly suggests a time in no more than 7.5% of cases, and the phone's code gives exactly the same answer as the tested code on every case.
The fresh set — 66 cases, about half on three new invented groups — was written by someone who was given the categories and not the method, so the cases could not be written to suit it. Both methods were run on it, the server method exactly as it runs, from a separate test project and never from the one members' data passes through.
| Right | Missed | Wrong suggestion | Costly-mistake score (lower is better) | |
|---|---|---|---|---|
| Guarded letter-triples, on the phone | 80% | 11 | 2 of 66 (3.0%) | 17 |
| Today's server method | 64% | 0 | 24 of 66 (36%) | 72 |
The rule was met, so suggested times move to the phone. The finding that matters most is the server's: it suggested a time for almost anything, including another person's activity and cancelled events. The guarded method misses more — mostly titles that mean the same thing in different words, which a member then sets by hand — and is wrong far less often.
4. Legal basis and consents
No consent purpose is involved: the change removes flows rather than adding one. Each feature still runs on the member's own act — typing a title, pressing Search.
Privacy policy (updated with this change): suggested times and meal search are described as worked out on the phone; the model section no longer lists suggesting a start time; the outcome counts are named, with what they hold and what they do not; a Device-only group's task search is described as working on the phone by spelling. The in-app explanation of automated decisions says the suggested time is a comparison of spellings on the phone, not a model.
5. Risks and mitigations
| Risk | Who is harmed | Mitigation | Structural or conventional? | Residual |
|---|---|---|---|---|
| A parent types "Kit footy training" and the form fills in Ada's training time, because the two titles share most of their letters | the child and the parent driving | Other-person check: the people a title names are its words that are a member's name or a relative ("Mum", "Nan"); if the closest past event names different people, nothing is suggested. The suggested time is shown before saving and never overrides a time somebody set | Conventional, test-pinned | A person named in a way the check does not know (a nickname, a friend) is not recognised |
| "No swimming this week" fills in the swimming time | the member | Negation check: a title with "no", "not", "cancelled", "skip", "postponed" or a word like "can't" suggests nothing, and a past event titled that way is never a candidate | Conventional, test-pinned | Other phrasings ("Trivia's off tonight") are not caught — one of the two wrong suggestions in §3.2 |
| "French class" fills in the Hindi class time because both are "… class" | the member | Shared-word check: a past event is a candidate only if it shares a distinctive word with the title — not "class", "appointment", "lesson", "night" or a joining word — allowing for misspellings and shortenings | Conventional, test-pinned | Two different things that share a distinctive word can still match ("Soccer boots shopping – Ruby" → Ruby's soccer training, the other wrong suggestion in §3.2) |
| A future change quietly keeps sending the typed words to a server "as a fallback" | the member and whoever the words name | The phone versions replace the server calls rather than sitting beside them; automated tests of the new-event form and the meal library record every request the flow makes and fail if any carries what was typed | Conventional, test-pinned (full-flow network tests) | Old app versions keep today's behaviour until they update |
| The phone's code and the tested code drift apart, so what ships is not what was measured | members | An automated check replays every case of all three test sets through the phone's code and fails on any different answer | Conventional, test-pinned | — |
| The past-events read shows the phone more of the group's past than a member could otherwise see | members whose events the reader could not see | The read goes through the member's own access, so row security decides what reaches the phone, exactly as the calendar does | Structural | — |
| A sealed title this phone cannot open is compared as the placeholder word | the member | Rows this phone cannot open are dropped before comparison | Conventional, test-pinned | — |
6. Structural versus conventional
Structural: the past events, tasks, plans and recipe names reach the phone only through the member's own access; the outcome counts table accepts inserts only, holds no title or member column, and is deleted with the group; the new app code contains no call to the two server comparisons it replaces.
Conventional, each test-pinned: that the new-event form and the meal library make no request carrying the typed words (full-flow tests with the network recorded); the three checks; that rows this phone cannot open are skipped; that the phone's code gives the tested answers; the wording on the search screens, which says "spelling" and never "meaning" for the phone's search.
If a model is ever adopted — for task search, where it helped — this assessment is revised before the code, and gains:
- the size, measured against the 40 MB we allow for this feature (our test builds were over it);
- the model file, either shipped inside the app or downloaded from our own storage at a pinned version with a checked hash — never fetched from a third party at run time;
- vectors for the group's rows, kept in memory, labelled with the account, the group and the exact model version; if ever kept between sessions, encrypted under the member's own key, excluded from device backups, and deleted on sign-out, on leaving the group, and when the row is edited or deleted;
- numerical agreement with the reference the model was evaluated with, processing one title at a time.
7. Best interests of the child
Two children again: a child named in a title or task, and a child using the feature.
- A child named in the group's records is the reason this change is worth making. The group's calendar is a running description of its children's appointments and school life, and until now up to 150 of those titles left the phone each time somebody typed a new event that was not an exact match. After the change they do not.
- The other-person check targets the mistake most likely to reach a child: another child's activity time filled in for this one.
- A child using the app. Suggested times and meal search work the same for everyone, including children and Device-only groups, since nothing leaves the phone. Task search by meaning stays unavailable on a child's account in other groups, as before; in a Device-only group a child can use the on-phone spelling search like anyone else.
- The safer design would be not to suggest times at all. We keep them because a suggestion never overrides a time somebody chose and is visible before saving, and because the measured rate of wrong suggestions fell from 36% to 3%.
8. Residual risk we accept
- Suggested times still make some wrong suggestions — 2 of 66 in the fresh test — and miss more titles that mean the same thing in different words. The outcome counts are how we will learn the real rates.
- Task search at the Australia and Global levels still sends the query and task text to our server. A spelling-only search is weaker for questions about meaning; that trade was not made for those groups. It will stop working for any group whose task text is sealed unless it moves to the phone first.
- A child's account in a group above Device-only still has no search on Return, although the spelling search would send nothing. Offering it is a separate decision.
- Old app versions keep the old flows until they are updated; the server functions stay up for them and are switched off only when no supported version needs them.
- The reads of past events and recipe names tell our database that a member opened the new-event form or used meal search — not what they typed.
- The tests are small and synthetic. 66 fresh cases can show the guarded method is much better than the server one; they cannot promise an exact mistake rate.
9. Review trigger
Re-read and revise this assessment before:
- adopting a model for any of the three features — §6's obligations become part of the design, and the app-size cost is stated;
- adding any request to these flows that carries the typed words, a title or a task, for any reason including "improving suggestions";
- keeping anything on the phone between sessions that is derived from the group's titles;
- widening what is compared (completed history, notes on events, baby records, chat);
- changing any of the three checks, the setting that decides how close is close enough, or what the outcome count holds;
- switching off a server function — this assessment is then updated to say it is gone.
10. Checklist against exposure draft s 38(2)
| s 38(2) | Requires | Answered in |
|---|---|---|
| (a) | nature, scope, context, flow and purposes of handling children's personal information | §§1–3 |
| (b) | why the collection is strictly necessary | §2 — nothing new is collected, and what leaves the phone shrinks |
| (c) | lawful and fair collection | §4 |
| (d) | consistency with the best interests of the child | §7 |
| (e) | how we comply with the Code and the Act | §4 and §6 |
| (f) | risk of harm to children | §5, §7 |
s 38(3): this assessment preceded the build. s 39: listed on the published register.
11. Sources
Primary: the Children's Online Privacy Code exposure draft, ss 10, 38, 39.
In repo: scripts/embeddings-eval/ (both evaluations: the test cases, the fresh held-out set,
the pinned model files, eval.py and guarded.py) and
docs/ml_experimentation.md ("2026-09-30 — on-device embeddings" and "2026-09-30 — guarded
letter-triple time suggestion": the decision rules written before each run, and the results);
lib/letterTriples.ts (the phone's method), lib/__tests__/letterTriples.parity.test.ts and its
fixture (the phone reproduces the tested answers); lib/scheduleLookup.ts and
components/Schedules/CreateEventModal.tsx (suggested times on the phone), with
components/Schedules/__tests__/CreateEventModal.onPhone.test.tsx (the full-flow network test);
lib/mealSearch.ts and components/Meals/ExplorePlans.tsx (meal search on the phone), with
components/Meals/__tests__/ExplorePlans.search.test.tsx; lib/taskSearch.ts and
hooks/useTaskSearch.ts (the Device-only task search); the migration that adds the letters
stage to event_time_lookup_stats; agent-server/src/timeLookup.ts and
supabase/functions/semantic-search-plans/index.ts (the server versions kept for old app
versions); docs/schedule_event_auto_timing_plan.md (the suggested-time design and the outcome
counts); docs/privacy_personas_plan.md §8.6 and §14.1 (the plan and decisions this implements);
semantic task search (the server task search that stays).