← All privacy impact assessments
PIA: The assistant reads a photo or a PDF you attach
Status: Assessed and approved with conditions on 25 October 2026, before any code was written. The server half was built on 28 October 2026 and is switched off: nothing on this page reaches a member until we turn on one platform switch, and we won't do that until the app half, the staged changes described in §3.4, the privacy policy and the evaluations in §5 are all in place. This page describes the server half as built and names every part that is not built yet. Written: 25 October 2026 · Last revised: 28 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).
The labels A1–A27 (conditions), K1–K13 (risks) and R1–R9 (residual risks) are the numbering of our internal approval of this design (PIA-011). We keep them here so each claim below can be traced to the condition it rests on.
1. Purpose and scope
A member wants to show the assistant a school notice, a receipt, a poster or a letter and ask "put this on the calendar" or "what do I need to bring?", instead of typing it out. One sentence for why: reading the file is the same act as the member typing what is in it, done for them.
In scope: an adult (or a 16- or 17-year-old who has already turned on AI features) attaching up to five files to a typed message in their own Assistant tab: photos from the phone's library, a photo taken there and then with the camera, and PDFs. What our server reads, what goes to Google, what is kept and where, what the file's contents can and can't make the assistant do, and what our improvement records say about it.
Out of scope, covered elsewhere: Mail Sifter's own pictures, whose reading step this feature reuses unchanged (forwarded email, "Pictures in Mail Sifter"); where the assistant's model runs (cloud inference §12); "Help us improve the assistant" itself (assistant tracing); how the assistant conversation is stored on the phone.
What is built, and what is not (28 October 2026).
- Built, switched off: the server's read request (§3.1), the guardrail (§3.3), the gate on any request that carries what was read (§3.4), outline-only tracing (§3.5), the database columns, the daily picture count and the first-use record (§3.6).
- The app half, not built yet: the + button, the picker and camera, removing location and camera details on the phone, sealing what was read into the member's message, the first-use sheet, "What the assistant read" beside each file, the guardrail's and backstop's replies, the Forget the file chip, replies that load no remote pictures and show links in full, keeping files and their names out of crash reports and "Send to GroupApp".
- Not built yet, and required before the switch: staged changes with an Approve button (§3.4). Until then an attachment turn can only read.
- Separate: the privacy policy and Child Privacy Policy text (§4).
2. Data involved
| Item | What it holds | Whose | Children's? | Sensitive? | Free text? |
|---|---|---|---|---|---|
| A photo (library or camera) | pixels: printed words, faces, homes, plates, screens, labels | the member's, and anyone in it or named on it | often: school notices, class photos, children's faces | can be: a medicine label, a letter, a bank card | yes, in effect |
| A PDF | its text layer, first 20 pages | as above | often | can be | yes |
| What was read | the photo's words or the PDF's text, credentials masked, capped | others' words, in the member's conversation | possibly | possibly, including health | yes |
| The guardrail check | the same masked words, nothing else | as above | possibly | possibly | yes |
| The guardrail's outcome | per file: used or not, a closed reason, and a quote of at most 60 characters shown once | the file's own words, for the quote | possibly | no | the quote only |
| "Forget the file" marker | a message id: from here on, earlier files aren't used | the member | no | no | no |
| A file's name | can name a child ("Ada_report.pdf") | the member's | possibly | possibly | yes |
| Daily picture count | member, Sydney date, a number up to 20 | the member | no | no | no |
| First-use record | member, notice version, time | the member | no | no | no |
Not collected, and could have been: no stored copy of any file, thumbnail, bucket object,
cache or disk copy on our side; no location or camera details (removed on the phone, and the
server re-encodes every picture again so only pixels remain); no description of a person (the
reading instruction asks for words only, with [photo] or [logo] where a picture is); and
no file name ever reaches our server: the server calls files "picture 1" and "PDF 2", and its
request shape refuses any other field.
Strictly necessary? For each item, the member asked for it: they chose the file and asked a question about it, so reading it is the service itself. The children's information in it is not collected for its own sake: it is in the file the member chose, and we read words only, keep what was read only in the member's own sealed conversation for its 30 days, and send it nowhere else. The daily count and the first-use record exist to cap cost and to show the notice before use. The file name is the one thing we don't need, so it stays on the phone.
3. Flows and locations
3.1 Two requests, and pixels reach neither turn (A5)
Request 1: reading the files. The phone sends the files to our assistant server's read
request (POST /api/assistant/attachments, in Google Cloud, Sydney). The group it is for travels
in a header, so every gate runs before a byte of the body is read, in this order, each one a
fixed refusal with no model call (A2):
- signed in;
- not a child account;
- not a 16- or 17-year-old without their own AI yes;
- not a shared display's account;
- the group's privacy level readable through the member's own access, and not Device-only;
- the member has acknowledged privacy policy version 3.14 or later, and has seen the first-use sheet at its current version;
- the platform switch
assistant_attachmentsis on; - the member's weekly allowance, the group's allowance and the platform's spending ceiling.
Only then is the body read, by this request's own parser and limit (every other request keeps its 1 MB limit), behind its own limit of 10 requests a minute per member and its own error handler, which answers a fixed code and logs only the kind of error. The body may hold each file's kind, type and bytes, and nothing else. Then, in request memory only:
- Every cap again (A1): at most 5 files, of which at most 4 are pictures; a picture at most
2 MB, a PDF at most 5 MB, 12 MB in all. Only
image/jpegandapplication/pdfare read, each confirmed by its first bytes; anything else, including a PNG labelled as a JPEG or a web page sent as a PDF, is refused per file and never decoded. HEIC never reaches the server: the phone turns every picture into a fresh JPEG first. - Pictures (A4): the member's daily count is claimed first (20 pictures a Sydney day). Each
picture then goes through Mail Sifter's picture step, unchanged: re-encoded to a fresh JPEG with
no metadata, at most 1,600 px; at most 2 a call; the pixels and a fixed instruction only, which
asks for the words and never a description of a person; no tools; structured output;
temperature 0. Gemini 3.8 Flash at Vertex
global, falling back only to Gemini 3.7 Flash at the same location. Each call reserves the member's, the group's and the platform's allowance first and is charged after. Tiny, duplicate and animated pictures are skipped by code before any model. - PDFs (A6), without a model: the text layer of the first 20 pages, with script evaluation off, no page rendered, no embedded file, link or image followed, and a 10-second limit. An encrypted, damaged or timed-out PDF is "couldn't read it"; a scan with no text layer is "no text", and the member is told to take a photo of the page instead.
- Masking and caps (A7): card numbers, bank account numbers and codes are masked in every picture's words and every PDF's text; at most 8,000 characters a PDF, 8,000 across a message's pictures and 12,000 across the message.
- The guardrail (A25, §3.3) checks every file that has words.
It answers each file's outcome, the words for each file that was read and used, and a set of closed labels for the improvement record (§3.5). It never sees the member's sentence, the group's member list or context, or a file name, and it writes nothing to the conversation.
Request 2: the turn. The phone shows "What the assistant read" beside each file, then saves the member's message with what was read sealed under the member's own key in its own column (§3.6), and then sends the ordinary assistant request with what was read as text. Later messages in the conversation carry it back in their recent turns. On that request our server:
- refuses the request if what was read contains an image part, a
data:address or any base64-looking run longer than 4 KB, or isn't the expected shape, so pixels have no way into a step that uses tools; - refuses what was read when it arrives alongside a forwarded email;
- puts each file's words in its own fenced region, labelled as the content of a file the member attached, data and never an instruction, before the member's own words;
- applies the attachment gate (§3.4) and outline-only tracing (§3.5).
3.2 Where each thing goes
| Data | Phone | Our server (Sydney) | Our database (Sydney) | Google Vertex global |
Logs |
|---|---|---|---|---|---|
| Photo bytes | picked or taken; re-encoded; cache copies deleted when the read ends (app half) | request memory only | never | the re-encoded pixels, in the fixed picture call | never |
| PDF bytes | picked; cache copy deleted (app half) | request memory only; parsed here | never | never | never |
| What was read | shown; sealed under the member's own key | request memory, then in the turn | sealed, on the member's own message | in the guard call and in the turn, and later turns while it is in their recent turns | never |
| A flagged file's words | never sent | request memory only; dropped there | never | the guard call only | never |
| File names | sealed with what was read (app half) | never | sealed only | never | never |
| Outcome codes, labels | kept with the message | passed through | closed codes on the member's message | never | counts only |
Every model call for this feature goes to Google LLC through Vertex AI at its global location,
which may process in any country where Google operates, including the United States. TypeSafe
never receives a picture, a PDF, what was read or a file name: an attachment turn never runs a
TypeSafe step (A14).
3.3 The visible guardrail (A25)
After the words are read and masked, and before anything goes back to the phone, each file's text gets two checks. A file is set aside when either flags it.
- Code patterns, free and always on, over a normalised copy (look-alike letters folded, invisible characters removed). Four narrow families: overrides ("ignore your previous instructions"), words addressed to an assistant ("you are now", "Assistant, …"), forged role labels and chat-template markers, and app actions (remove, invite, delete, post to the group) only when addressed to an assistant. A cue that needs an addressee never flags on its own, so "ignore the old date" and "remove shoes before entering" pass.
- One small model check: every file's masked words, each in its own fenced region, in one call
to Gemini 3.5 Flash-Lite at Vertex
global, the same processor, location and terms as the turn. It sees only the masked words: never pixels, the member's sentence, the member list, the group's context, a file name or earlier turns. A fixed instruction, no tools, temperature 0, thinking at its lowest setting (Vertex does not accept "off" for this model), a 5-second limit, one retry, no other model, and a fixed verdict. The only free text it can return is a short quote, kept only if it appears word for word in that file's text. If it times out, runs out of capacity, can't be reached or answers something unreadable, the patterns alone decide and the gate in §3.4 still holds. Any other failure, the budget kill switch above all, means no file in the message is used ("not now"). If its allowance can't be reserved, no file is used either, so nothing is used unchecked because the budget ran out or the service was switched off.
A file that is set aside is not used. Its words are dropped in the server's memory: not sent to the phone, not sealed, not in the turn or later turns, not logged. The phone gets the outcome, a closed reason and, at most, a quote of 60 characters and 8 words that appears in the file exactly, with no link or markup. The quote is shown once and never saved. The reply is fixed words the phone shows from the outcome (app half), never a model's, and says nothing was used.
It is a filter, not a boundary. It will miss some files written to slip past it, and it will set aside some ordinary ones. What holds whatever it decides is §3.4. Its catch rate and false positives will be measured on invented files before the switch (§5, A19); a number for that set, not a promise about files in the wild.
3.4 What a file can make the assistant do: the attachment gate (A8)
One rule decides it: a request is an attachment turn when it carries what was read from any file, in this message or in any recent turn the phone sends. Our server sets that from the request's own contents after everything else in it is read, so a request can neither claim it nor shed it. It holds whether or not the guardrail flagged anything. On an attachment turn:
- Only six parts of the assistant run: calendar, tasks, the shopping and pantry list, the meal planner, conversation, and group analytics (answering only). Group management, the baby tracker and games are dropped by name before they run, and the member gets a fixed sentence chosen by code ("I can't change members or group settings while we're looking at a file. Forget the file and carry on?"), never a model's words.
- Reads only, for now. Every part binds only a fixed list of tools that read
(
ATTACHMENT_TURN_TOOLS, applied throughtoolsForCaller, the one filter every part's tools pass through). A tool not on that list is not bound, so a new tool reaches an attachment turn only once someone decides it is a read. Nothing can be added, changed, ticked off, deleted, posted or sent for anyone else on an attachment turn. This is a decision of 28 October 2026: the approved design lets a file's turn propose changes to the calendar, tasks, shopping list or meal plan as cards that write nothing until the member taps Approve, and Approve writes exactly the card. That needs work the typed assistant doesn't have yet, so it comes in the next change to our server, and the switch stays off until it is there. - No TypeSafe step and no shortcut route: the faster commands, the predefined answers, Jev's routing and the request split are all off for an attachment turn (A14).
- Group analytics answers only: its tools are all reads, and the answer goes only to the asker's own conversation.
Because the gate also holds on later messages while the reads are in their recent turns, "remove Sam from the group" sent just after attaching a poster gets the fixed sentence and a Forget the file chip (app half, A26). Tapping it stops the phone sending every earlier file's words and the replies to them (each reply replaced by a fixed placeholder, since a reply can restate a file), records a marker on the member's next message so it survives a reinstall or another phone, and re-sends the member's own sentence as an ordinary typed request. It does not remove what was read from the sealed message, which stays for its 30 days (R5): the chip says "forget" and "stop using", never "delete".
3.5 Improvement records (A12, A13)
For a member who turned on "Help us improve the assistant": any request carrying what was read, any message that carried a file at all (even if nothing was used), and the sentence re-sent after Forget the file are recorded in outline only, like a forwarded email: no message, file, instruction, tool or reply words. The read request is not traced at all, and neither model call in it carries a tracing callback. The outline gains closed labels only: the kinds of file, a count bucket, each file's outcome, the guardrail's result, which pattern families hit and the model's reason (never the text, the matched words, the quote, positions or the pattern), the guard's latency bucket and tokens, which part the gate dropped, and whether the file was forgotten.
Our nightly improvement labels (assessed in HQ PIA-009) treat any such record like a forwarded email's: fixed-list labels only, never a model reading of it and never a rewritten test case. The label format moved to its second version for these columns; first-version labels stay as they were, never rewritten. The guardrail's false-positive rate in use is estimated only from these labels and the evaluations, never by reading a set-aside file.
3.6 Retention and deletion
| Artefact | Where | Kept | Account deletion |
|---|---|---|---|
| File bytes | phone cache; our server's request memory | the request; the phone deletes its cache copies when the read ends (app half) | n/a |
| Pixels at Google | Vertex global |
Google's terms: request-response logging off (verified 31 October 2026); abuse monitoring may log a flagged prompt for up to 90 days; in-memory cache up to 24 hours, durable caching off (§8) | not reachable by us |
| Guard check | Vertex global, Flash-Lite |
the request; Google's terms as above | not reachable by us |
| What was read, and file names | chat_messages.sealed_attachment_reads, on the member's own message, sealed under their own key |
with the message: 30 days | deleted with the message |
| What was read, sent again | recent turns in later requests | the request; none after Forget the file | n/a |
| A set-aside file's words; the quote | server memory; the quote on the phone's screen | the request; the quote is shown, never saved | n/a |
| Outcome codes, forget marker | attachment_outcomes, attachments_forgotten_before on the member's message; no words |
with the message: 30 days | deleted with the message |
| Finished reply | the reply hold, in server memory | up to 5 minutes, as for any reply | n/a |
| Daily picture count | assistant_attachment_picture_days, counts only |
7 days | deleted |
| First-use record | assistant_attachment_notices |
with the account | deleted |
| Logs, spend ledger, outline | Cloud Logging, the spend ledger, LangSmith | counts, codes and labels only, existing retention | existing |
The database holds these properties itself: the sealed column must be empty unless the message is sealed, and can hold only base64; the outcome column holds only the closed list of codes; only a member's own message, never an assistant reply, can carry any of the three; members keep insert and read only on their messages, with no update and no delete; no member can read or write the daily count except through one function that can only add to their own; and our server never reads or writes any of the three columns.
4. Legal basis and consents
No new consent purpose. Reading a file the member picked, to answer what they asked, is the assistant doing what it already does with typed words (APP 6, below). The member is told, not asked:
- A first-use sheet before the picker or camera first opens (app half): what is read, that a photo goes to Google's Gemini in any country where Google operates, that other people's names and faces and children's go too, that the file isn't kept, and that what was read is kept, encrypted, with the message for 30 days. Recorded as a notice, not a consent; our server checks it on every read request, and it is shown again when its version changes.
- The privacy policy, version 3.14, which carries this feature's lines; our server refuses every read until the member has acknowledged it. Until version 3.14's text is final, our server holds a copy of its working identifier; if the two disagree, reads are refused (it fails closed). The Child Privacy Policy gains a sentence telling children that an adult may show the assistant a photo or document with them in it, and that Google's AI reads its words, not their face.
- 16- and 17-year-olds: their existing AI yes covers it, and its wording already says what they ask goes to Google's Gemini in any country and is deleted after 30 days. They are not asked again.
- Under-16s, child accounts, the shared display and Device-only groups: refused by our server before anything is read.
APP 6 (use and disclosure). The primary purpose is answering the member about the file they chose and sent. What was read is used for that answer and for the follow-up questions in the same conversation, and for nothing else: it never reaches TypeSafe, "Send to GroupApp" sends the sentence and reply but never what was read or a file name (app half), and the improvement records carry labels only.
APP 8 (overseas disclosure). A photo's pixels go to Google at Vertex global, the assistant's
existing processor, location and terms. What is new is the kind of data: a face and a scene can't
have names replaced. A PDF is read on our server in Sydney and only its words travel, as typed
words do; the guardrail sends words, never pixels. We make no zero-retention claim. Google's
data-governance page says request-response logging is off unless a project turns it on; in our
production inference project it is off for 3.8 Flash and 3.7 Flash (checked by the founder on
31 October 2026; the project's audit trail shows no change to it, ever). If Google's safety
classifiers flag a request, its prompt, a picture included, may be logged for up to 90 days and
reviewed by Google staff (the register's Argon amendment). Vertex's implicit cache: in-memory,
project-only, up to 24 hours, never used for training. Durable (at-rest) caching is off in our
inference project (EPHEMERAL, set 31 October 2026 by the founder and verified with a
read-back; Security's durable-cache ruling of 31 October, on Google's pages "Last updated
2026-10-30"). Turning it back on needs Security (§8).
APP 11 (security). The file exists only in the request's memory: no disk, temporary file, bucket, table, cache or queue, and an automated check scans the read code for any storage call. What was read is sealed under the member's own key, a key our server does not hold. Logs carry counts and fixed codes only, never bytes, words, file names, a request's body or an error's message, and a check covers the new code. The PDF parser runs with script evaluation off, caps and a time limit (R7). The read request has its own body limit, rate limit and error handler.
Lawful and fair (s 38(2)(c)). The member chooses each file and is told, before the first one, who reads it and where. People in the photo are not told (R8).
5. Risks and mitigations
Likelihood and impact at our current scale (about 100 invited members), before and after the conditions.
| # | Risk | Who is harmed | Before → after | Mitigation | Structural or conventional? |
|---|---|---|---|---|---|
| K1 | A child, a young member without their AI yes, a Device-only group or the shared display gets a file read | children; groups that chose Device-only | Medium → Low | the gates in §3.1, in order, before any byte is read | code before any model, each gate pinned by a check that counts zero model calls and zero bytes read |
| K2 | Location or camera details reach Google | the member; people at that place | Medium → Low | re-encoded on the phone with no metadata (app half); re-encoded again on our server; only JPEG accepted | server half: code, pinned by a check with a GPS-tagged picture; phone half: to be pinned when built |
| K3 | Pixels, the member list or the group's context reach a step that uses tools | everyone in the photo | High → Low | two requests; the turn refuses image parts, data: addresses and long base64 runs; the picture and guard calls bind no tools |
code, pinned |
| K4 | A file's text makes the assistant act (manage members, the baby tracker, delete, post) or steers an answer | the group | High → Low (R4) | the guardrail (filter); the attachment gate (boundary); reads only for now; evaluations before the switch | gate: structural; guardrail: conventional |
| K5 | What was read is stored unsealed, or an older app shows it and sends it back as ordinary words | the member; people in the file | Medium → Low (R6) | own sealed column, base64 only and only on sealed messages; older apps don't read that column; seal or drop on the phone | the column rules are database constraints; seal-or-drop is app half |
| K6 | A file, its words or its name reach logs, crash reports, traces or feedback | people in the file | High → Low | counts and codes only; no file name reaches our server; outline-only tracing | server: code, pinned by log and tracing checks; crash reports and feedback: app half |
| K7 | Other people's and children's words reach LangSmith or our improvement labels | people in the file, children | High → Low | outline only; labels from fixed lists; no model reading, no rewritten case | code, pinned |
| K8 | TypeSafe receives file content | people in the file | Medium → Low | no TypeSafe step on an attachment turn | code, pinned by a check that counts TypeSafe calls |
| K9 | Pictures run up cost | us; the group's allowance | Medium → Low | 20 pictures a member a day; every call reserves first; the budget kill switch fails closed | the count is a database function and constraint; reservations are code |
| K10 | The feature is live before the notice and policy reach phones | every member | High → Low | policy version and first-use record checked per request; switch inserted off | code and a database row |
| K11 | A crafted PDF or a huge body crashes or slows the server | everyone using the assistant | Medium → Low (R7) | caps before parsing; own body limit; script off; time limit | code, pinned with crafted fixtures |
| K12 | The guardrail sets aside an ordinary file, or its quote or reply leaks or accuses | the member | Medium → Low (R9) | narrow patterns; a quote only from the file's own words; fixed reply that never says "injection", "prompt" or "delete" | code and copy checks; the rate itself is measured, not enforced |
| K13 | A reply sends group data out through a remote picture or link a file planted | the group | Medium → Low | replies load no remote pictures and show links in full (app half); reads only | app half, to be pinned when built |
Evaluations before the switch (A19). Invented files only: no real person or child. At least 60 attack files (plain overrides, instructions about members and settings, steering inside the allowed parts, forged markers, split and disguised text, at least three languages besides English, and text addressed to the guard itself) and at least 150 ordinary ones (posters, school notes, receipts, menus, recipes, medicine labels, terms and conditions, with traps such as "ignore the old date" and "you are now enrolled"). The marks: at least 90% of attack files caught, at least 98% of plain English overrides; no more than 2% of ordinary files set aside; no set-aside file's words anywhere; the guard adding no more than 1.5 seconds at the 95th percentile; and, with the guardrail turned off, no injected action reaching a write or a dropped part. The switch stays off until every mark passes.
6. Structural versus conventional
| Condition | What it holds | Status (28 October 2026) |
|---|---|---|
| A2 Gates before a byte is read | child accounts, young members without their yes, the shared display, Device-only, the policy and notice, the switch and the allowance refuse before the body is read | Structural: code that runs before any parsing or model, in a fixed order; each gate pinned by a check that counts zero model calls and zero bytes read. The switch is a database row read per request; anything but a plain "on" is off |
| A5 Pixels never reach a step with tools | the turn carries words only | Structural: two separate requests; the turn refuses image parts, data: addresses and base64 runs over 4 KB before anything is built; neither model call on the read request binds tools. Pinned |
| A8 The attachment gate | which parts run, and that nothing is written | Structural: the disallowed parts are dropped before they run; write tools are not bound (only the read list is), so no model output can call one; the flag is set by our server from the request's contents. Pinned by a check that drives a turn with a stubbed model. The day staged cards arrive, the Approve step must hold the same way |
| A10 Sealed under the member's own key only | what was read is never stored readable | Structural for the database's part: the sealed column must be empty unless the message is sealed and holds only base64; members can't update or delete a message; our server never touches the column (a check scans for it). The sealing itself, and dropping the reads if sealing fails, are app half |
| A12 Outline-only tracing | no file words in an improvement record | Structural for what was read: our server decides from the request's contents, and checks feed four kinds of attachment request through the real tracing path and look for words. Conventional for a message whose files were all set aside, and for the re-sent sentence after Forget: those carry no words of the file to leak, and are kept to the outline only because the phone sends a label saying so (app half) |
| A25 The guardrail | fewer files written as instructions reach the assistant | Conventional: a filter, measured by the evaluations, never a boundary. What it leaves out (a set-aside file's words) is code and pinned; how well it judges is not something code can prove |
| A26 Forget the file | earlier files stop being used | Structural for what forget removes: our server keeps no copy of what was read, so once the phone stops sending it, nothing on our side can bring it back into a turn, and the re-sent sentence is an ordinary typed request with the gate off. The removal from what the phone sends, the marker and the chip are app half, to be pinned by tests there. The backstop's sentence is fixed code, pinned by a copy check |
Also held by code and pinned: no storage call in the read code (A9); no file name in the request shape and nothing but counts in logs (A11); the picture call's request matches Mail Sifter's pinned instruction byte for byte (A4); the daily count and the 7-day sweep are database functions (A15, A24). Conventional: the reading instruction asking for words and never a description of a person (R3); Google's handling of what it receives (R1).
7. Best interests of the child
Under-16s have no assistant, so a child cannot attach a file. Children appear in files: a class photo, a school notice with names, a sports roster, a medicine label. That is the main case, not an edge case.
- What it gives a child: indirectly, an adult who gets the excursion date and the "bring a hat" right without retyping a notice.
- What it costs a child: their face, name, school or class can reach Google outside Australia in a file they didn't choose, and the words read from it sit in one adult's sealed conversation for 30 days. A face can't have its name replaced.
- The safer design, and why it was not chosen: reading the words on the phone, so no pixels leave it. The phones we support don't all offer a dependable on-device text reader for this, and it is the upgrade path we name (§9). We chose instead: words only, never a description of a person; never traced or labelled with words; no file kept; under-16s refused; and the 30-day bound.
- Where the adult's and the child's interests diverge: the adult wins the convenience, the child bears the exposure. The weight on the child's side is everything above, plus the first-use sheet telling the adult, in plain words, that children's faces and names go too.
- What the child is told: the Child Privacy Policy sentence in §4.
- Re-checked against the Children's Code before public beta and when the Code is registered (A23): the gates, the attachment gate, R2 and the Child Privacy Policy sentence.
8. Residual risk we accept
Accepted on approval, 25 October 2026.
- R1 Google's handling of pixels. Faces and scenes reach Google outside Australia and can't be pseudonymised. No zero-retention claim. On-device text recognition is the later fix.
- R2 People who chose nothing, children first. A school poster, a class photo or a note carries other families' children's names, schools and faces to Google. Their words sit in one adult's sealed conversation for 30 days and go back to Gemini on follow-up questions. Bounded by words only, no description, never traced, the 30-day sweep and under-16s having no assistant.
- R3 Imperfect reading. The reading instruction is an instruction, not a guarantee: a transcript can describe a person, miss a credential the mask doesn't know, or carry health details. The picture itself always goes whole.
- R4 Steering within the allowed parts. A file's text can still shape an answer, and once staged cards arrive, a card: a wrong date, a planted title or link. Bounded by the gate, by the member's Approve and by the evaluations. The guardrail lowers this for text written as instructions to the assistant, by a catch rate measured on an invented set; it does nothing for content that is simply wrong in a file's own voice ("Book at "), and a determined author can phrase past both checks. We say "fewer such files reach the assistant", not more.
- R5 No early deletion. What was read can't be removed before 30 days except by deleting the account. Forget the file stops its use, not its storage.
- R6 Replies restate files. A reply's own words ("the excursion is on 3 November") are ordinary reply text: on an older app, or once the reads have left the recent turns, a later request carries them as words and can be traced under "Help us improve".
- R7 Parsing untrusted files on our server. A parser bug could crash or slow an instance. The PDF time limit stops waiting, not parsing: one step of a crafted file can run past it. Bounded by the 5 MB and 20-page caps, script off and no storage; the upgrade is parsing in a separate thread with its own deadline.
- R8 Notice depends on the member. People in the photo are never told; the member is told once, plus one line beside the + button.
- R9 The guardrail is imperfect both ways. It will set aside some ordinary files and miss some written to slip past it. A set-aside file costs the member one retype and its words are never kept; a missed one meets the gate. Its false-positive rate in use is known only from labels, never from reading a file.
Also accepted, and conservative: the daily picture count counts pictures offered for reading, claimed before the first call, so a picture later skipped as too small or a duplicate still uses one of the day's 20.
Unverified, and to be recorded before the switch (as at 28 October 2026)
- Vertex request-response logging for the picture call: verified off (31 October 2026). The
founder checked our production inference project: off for 3.8 Flash and 3.7 Flash, and the
audit trail shows no change to it, ever. Implicit caching is
EPHEMERAL: in-memory only, up to 24 hours, with durable (at-rest) caching off, set and verified on 31 October under Security's durable-cache ruling. Abuse monitoring is as in R1 and the register's Argon amendment. Still unverified: request-response logging for the guard's 3.5 Flash-Lite call, which the check did not name. The guard sends words, never pixels; check and record it before the switch. - The evaluations (§5) have not had their paid run, so the guardrail's catch rate, false positives and latency, and the gate with the guardrail off, are unmeasured.
- The guard's Flash-Lite call has not yet been made against Vertex itself, only against stand-ins.
- The cost estimate (about US$0.30 for a member's 20 pictures a day, and at most about US$0.0026 a message for the guard) is from Mail Sifter's figures and unverified for this use.
- Nothing here has met a phone: the app half is not built.
9. Review trigger
- A new file type is accepted (a Word document, a spreadsheet, HEIC on the server, audio, video).
- PDF pages are rendered to pictures, or a scanned PDF is sent to a model.
- The reading instruction changes to describe objects, scenes or people.
- On-device text recognition replaces the picture call (and the disclosures in §4 shrink).
- A new way in: the share sheet, Shortcuts, App Intents, voice, an upload link, background upload, the shared display, or a Device-only group.
- A model, processor or region changes for the picture call or the guard.
- Staged cards with Approve arrive (§3.4); this page is revised before the switch.
- The guardrail gains a "use it anyway" button, or is dropped after the evaluations.
- Any of A2, A5, A10, A12, or "a set-aside file's words are never kept", is found broken in production: the switch goes off the same day, and this page is revised before it goes back on.
10. Checklist against exposure draft s 38(2)
| s 38(2) | Requires | Answered in |
|---|---|---|
| (a) | nature, scope, context, flow and purposes | §§1–3 |
| (b) | why collecting children's personal information is strictly necessary | §2: it is in the file the adult chose; we read words only and keep them only in that adult's sealed conversation |
| (c) | lawful and fair collection | §4 |
| (d) | best interests of the child | §7 |
| (e) | how we comply with the Code and the Act | §§4, 6 |
| (f) | risk of harm to children | §§5, 7, 8 |
s 38(3): assessed and approved before the code, and the switch stays off until the conditions above are met. s 39: listed on the published register.
11. Sources
- HQ PIA-011, "the assistant reads a picture, a PDF or a camera photo the member attaches", approved with conditions on 25 October 2026 (A1–A27, R1–R9), amended 25 and 27 October 2026; the decision of 28 October 2026 to ship reads only first. HQ PIA-008 (Mail Sifter pictures) and HQ PIA-009 (improvement labels).
- Google Cloud, Vertex AI data governance and zero data retention: https://docs.cloud.google.com/vertex-ai/generative-ai/docs/data-governance (read 22 October 2026, as cited in our assistant tracing assessment).
- The read request:
agent-server/src/attachments/contract.ts(caps, closed lists, the policy floor, the backstop sentences,ATTACHMENT_TURN_TOOLS),agent-server/src/attachments/route.ts(the gates in order, the request's own parser, limit, rate limit and error handler),agent-server/src/attachments/read.ts(caps, first-bytes check, the picture step, PDFs, masks, character caps),agent-server/src/attachments/guard.ts(the patterns and the Flash-Lite check). - The turn:
agent-server/src/attachments/turn.ts(the image refusal, fences, the gate, outline labels),agent-server/src/run.tsandagent-server/src/server.ts(where the gate and outline are applied),agent-server/src/wallAreas.ts(toolsForCaller),agent-server/src/improveTraces.ts(contentTraceable),agent-server/src/inboxPictures.ts(the picture step, unchanged). - Improvement labels:
agent-server/insights/schema.tsandagent-server/insights/select.ts(label schema v2, attachment roots). - The database:
supabase/migrations/20261028003342_assistant_attachments.sql. - The checks:
agent-server/checks/attachmentsRead.check.ts,agent-server/checks/attachmentsGuard.check.ts,agent-server/checks/attachmentsTurn.check.ts,agent-server/checks/tracing.check.ts,agent-server/checks/transcriptNotRead.check.ts,agent-server/checks/noContentInLogs.check.ts,agent-server/checks/inboxPictures.check.ts,agent-server/insights/insights.check.ts,__tests__/assistant_attachments.test.ts. - Unverified items: our known-issues register's entries for assistant attachments (28 October
- and Mail Sifter pictures (24 October 2026).