← All privacy impact assessments
PIA: Group inbox (forwarded email)
Amended 30 October 2026: deleting a group. An owner can delete a group. Members are told at once, and the group is deleted seven days later unless the group's owner cancels; meanwhile anyone can export their own data or leave. Deleting removes everything the group holds for everyone in it, children included: messages, photos (sealed or not), lists, routines, baby records, the group's inbox and its attachments, and its keys. Our backups expire within 90 days and a deleted group is not restored from them. A star rating a member gave stays, with no group attached. Copies of the group's events in connected groups say the group no longer exists.
Amended 31 October 2026. Mail Sifter's model calls move to Gemini 4 Argon at Vertex
global, with 3.8 Flash and then 3.7 Flash behind it on capacity errors: same processor, location and terms (cloud-inference §12, amendment of 31 October).Amended 4 October 2026. The Mail Sifter assessment runs on Gemini 3.8 Flash at Vertex
globalfor every group, with the email as written; TypeSafe's second judgment now applies to every group that uses Mail Sifter, still with names replaced and never for an email with health words (cloud-inference §12).
Shown in the app as "Mail Sifter" (renamed from "Group inbox" to "Email eater" on 16 September 2026, then to "Mail Sifter" on 19 September 2026; no change to the data, the flows or anything assessed below — the tool's on-screen name only).
Status: Built. The switch, the two tables and the retention sweep shipped 14 September 2026;
the screens to view and act on an item, the "turn into cards" extraction step, a sender-policy
filter, an admin's note to the assistant, and the settings screen moving from the group's own
management page into the tool itself all shipped 15 September 2026 (below, §§1–3, §5, §8). A
second revision, 16 September 2026, changed what happens BEFORE a member ever opens an item —
see the new subsection in §1 and the new rows in §§2–6 — and did not change anything about the
switch itself. A third revision, 18 September 2026, assesses a planned change to who a
card calls on — see "Planned: addressing the people an email concerns" in §1 — ahead of that
change being built; nothing about it ships yet. A fourth revision, 18 September 2026 (review
correction), fixes an overclaim the third revision made: whether a child's account can be kept
from seeing a card once it is shared to the household is a client-side (conventional) property,
not a database refusal — see §1 and §8. A fifth revision, 19 September 2026, updates §1 and §8:
a same-day database change now refuses a child's account, BY THE DATABASE, from reading the
pending item and the address — not merely kept from them by an absent tool — while the household-shared
card's child-visibility is unaffected and remains the conventional (client-side) property the
fourth revision described. A sixth revision, 22 September 2026, assesses a new, small surface
built the same day: the group chat now carries one quiet, unattributed system row — "New mail
arrived in Mail Sifter." — the first time mail lands in a given hour, naming nothing about the
email itself. See the new subsection in §1, the new row in §2, and §5, §6 and §9. A seventh revision, the same day, lets a group's owner or admin
act on ANY INBOX_PROPOSAL card from the Mail Sifter item screen, whatever its audience — see
the addition to §1 "As built", the new row in §5, and §9's new review trigger.
An eighth revision, 22 September 2026 ("attachment bytes: store, show,
delete with the item"), assesses the webhook fetching and storing the attachment BYTES
themselves for an allowlisted type under a fixed cap — not merely their names, as §§2–3
previously described — deleted by tombstone with the item; see the new material in §§1–3, §5,
§6 and §8. A ninth revision, 22 September 2026 ("calendar invitations become event options"),
assesses a stored calendar file's own event fields being read on a member's device — never by a
model — and offered as options on the same card the email itself produces, prepended ahead of
anything a model separately suggests, with the file's own words also reaching a model in their
own fenced region so a summary can still describe what the file said; see the new material in
§§1–3, §5, §6 and §9. A tenth revision, 22 September 2026 ("PDF attachments are read by the
assistant"), assesses a stored PDF attachment's text being extracted on our own server — not on a
member's device, because this app has no on-device PDF reader — under that member's own read
rule, capped in length and count, and handed to the model beside the email on the same turns the
body already reaches it on; a per-group switch, on by default, lets an admin stop this without
turning the feature that stores and shows the file off; see the new material in §§1, §3, §4, §5,
§6 and §9. An eleventh revision, 22 September 2026, adds a SECOND way in — sharing a page, a photo
or a file into the group from any other app on the same device, through the operating system's
own share sheet — alongside the one address this document already describes; see the new
subsection in §1 and the new rows in §§2–6, §8. A twelfth revision, 23 September 2026 ("onboarding
setup step: Mail Sifter in first sitting"), assesses offering Mail Sifter as an optional setup step
for adult members in standard groups where an admin can turn it on (or it is already on).
Turning it on records the member's consent and shows the address for copying. While the app is
in the foreground, this step checks for a forwarded email for up to three minutes, stopping
once an email arrives and presenting its proposed actions when assessment finishes. A thirteenth
revision, 30 September 2026 ("encrypted as it arrives"), assesses the group inbox keypair, built
and merged the same day but not yet released: once released, and once an owner or admin of the
group has opened Mail Sifter on an up-to-date app, a forwarded email will be encrypted as it
arrives and stored only as ciphertext, a share will be encrypted on the phone that shares it, the
assessment's free text will be encrypted field by field, and the group's note to the assistant
will be encrypted like event notes; see the new subsection in §1 and the additions to
§§2–3, §5, §6, §8 and §9.
Written: 2026-09-14 · Last revised: 2026-10-30 (deleting a group); 2026-10-12 (J6 built, not released; its four narrowings
recorded in §1, and its pre-registered measurement — experiment 014 — not run)
Nothing here is legal advice. Children's Code citations are to the exposure draft;
section numbers may move on registration (due 10 Dec 2026).
As built, 30 September 2026. Every earlier revision described above has shipped. The thirteenth revision — the group inbox keypair that seals a forwarded email as it arrives — was built and merged the same day it was assessed, matching the design with no deviation we found, but has not reached any group yet: it takes effect once our next database release ships and a group's phones have updated to the app version built alongside it. Until then, mail arriving at Mail Sifter is stored exactly as the rest of this document describes it today.
Revision, 6 October 2026 — at Standard, the keypair waits for our server's copy of the key, and an email the assistant cannot read says so. Built, not yet released. A group's first encrypted email (5 October) was encrypted to a keypair whose key our assistant server had never been given: every copy offered to our server had been refused for a month by a setting on our cloud project, now fixed. The assistant could not sort it, the app tried again every time it opened, and nothing on screen said why. From this revision, in a Standard group, an owner's or admin's phone makes the inbox keypair only once our server holds the copy of the group's current key that Standard already provides for; until then, mail is stored as it was sent, as for a group not yet set up. The same phones offer that copy again by themselves when it is missing. An encrypted email the assistant cannot read is not sent for sorting: its row says "Can’t sort yet", and an admin can let the assistant read it in one tap from the email; one encrypted under an older key says "Can’t be sorted". Either still opens on the group's phones. See the additions to §1 and §5.
Revision, 9 October 2026 (amended 10 October) — our server sorts each email as it arrives, for every group using Mail Sifter unless an owner or admin turns it off. Assessed before it was built; built the same day, not yet released, and behind a platform switch we turn on. Until now every sorting step ran on a member's phone, inside that member's own request, paid from their own allowance: an email sat unsorted until somebody opened the app. With Sort emails as they arrive — on by default since our decision of 10 October, which reversed the off-by-default, consent-class design of 9 October — our server sorts each new email within about a minute, with nobody's app open, paid from a weekly amount set aside for the group (A$0.50 a week unless we agree more), and raises the same card a phone would. This reverses three things this document used to call structural: that no server-side job ever sends an email to a model, that sorting happens only on a member's session, and that a person is charged for it. It adds new structural lines in their place: our server refuses a Device-only group by code before anything is read, it writes a key-use record before it opens anything, a card it raises always has its words encrypted, and only an owner or admin can turn it off (or back on), with the group told either way. See the new subsection in §1 and the additions to §§2–6, §8 and §9.
Revision, 10 October 2026 — two changes assessed before either is built: a deadline the email itself states becomes the created task's own due date and time, and Mail Sifter offers to set up or change a repeating arrangement an email describes. Both are PLANNED. Nothing in this revision ships yet. Today a date the assessment read out of an email reaches a created EVENT as that event's own start, which our server can read and always could; the same date on a created TASK survives only inside the task's notes, which are encrypted on the phone that writes them, and the task itself carries no deadline at all. The first change makes the two match: a member can set the date and time on the card, and their tap writes them to the task's own due date and time — plain columns, because a reminder's time and whether a task is late are worked out from them. Nothing is guessed, and the email's own words stay in the notes. The second change lets the sorting step ask one more question — is this a repeating arrangement, or a change to one? — read a schedule from the email's own words, ask Jev which of the group's existing routines an email concerns, and offer one new option on the card that changes nothing until a member taps it. Two things in that are new and are said plainly below: it sends the group's OWN routine titles, with names replaced, to a second processor for the first time, and it adds a card option that is neither a task nor an event, which widens by one word a closed list this document leans on. See the two new subsections in §1 and the additions to §§2–6, §8, §9 and §11.
Revision, 11 October 2026 — BOTH of those changes are now BUILT, NOT RELEASED. A deadline the email states now reaches the created task's own due date and due time, exactly as assessed: shown on the card in the group's own zone beside the email's own words, editable there with the same pickers an event option uses, written only by the tap that creates the task, and never filled in for an email that stated none — a task option takes only a date the email actually stated, never a reading of its free text. One thing is narrower than the assessment allowed for: nothing on the card offers a reminder, so the reminder choice those columns feed is always written as "off" and no reminder is ever set from an email; a member who wants one chooses it on the task's own sheet afterwards. No release carries any of this.
The repeating-arrangement change (J6) is now built too, and is NARROWER than this document assessed in four ways that each reduce what was accepted. All four are stated in full under "Built, not released: Mail Sifter offers a repeating arrangement" in §1, and in short:
- The closed list of option kinds did NOT widen. The assessment accepted a THIRD word beside "task" and "event", and said §§5, 6 and 8 rested on that list being two words long. What was built keeps it at two: the routine option is its own FIELD on the card, which no model writes — it is built by code out of Jev's two answers. So the "Hey GroupApp, remove Sarah" defence is exactly as strong as it was, rather than one word weaker.
- A routine option is never stored on the email's own record. It travels on the reply and onto the card and nowhere else. One consequence a member can see: "Make cards anyway" on an email the assistant judged unlikely offers no routine option, because the stored assessment does not carry one.
- Only two kinds of schedule are read: every day, and named days of the week. A fortnightly or monthly arrangement is not read at all, because it is measured from a first date that mail of this kind rarely states.
- No reminder is ever written, exactly as for a task's deadline above — the lead is left wherever the household already set it.
One thing is also narrower than assessed on OUR SERVER's sorting path only: it offers to set up a NEW routine, and does not yet offer to change an existing one, because the leased record it would read the group's routine titles from does not carry them yet. A member's own phone offers both. No release carries any of this either. See "Built, not released" under §1 below.
1. Purpose and scope
A group can turn on an email address of its own — <token>@in.groupapp.ai — and forward mail
to it: a school newsletter, a camp permission slip, a plumber's invoice, a party invitation.
The mail lands as a pending item the group can see. The next active adult member who opens
the app has their own assistant look at it once — see "Assessed on arrival" below — and from
then on a member can turn it into ordinary tasks and events, through their own assistant
session, or dismiss it. Nobody else's mailbox is connected, nothing is read on a schedule, and
we never reply to the sender.
Assessed on arrival (added 16 September 2026)
A pending item does not wait for a member to decide it is worth opening. The first ACTIVE ADULT member of the group who opens the app, or this tool's own screen, after an item arrives has their assistant read it once — one structured question, on that member's own session, under their own group's region and spending rules — and the answer sorts the item into one of two paths:
- Likely worth acting on: the assistant's options (a task, an event, or several) are turned into a card every member of the group sees and can act on — nobody's records change until a member taps to create the chosen options.
- Unlikely to need anything: the item is set aside with the assistant's one-line reason attached, and any member can still ask for a card to be raised from it by hand.
A member may also write a line addressed to the assistant inside the forwarded email itself ("Hey GroupApp, these tickets are for Bob and Jane") to steer which options are suggested, their titles or dates, and who they are suggested for — see the new row in §2 and the new risk in §5. A child account never triggers this and is refused server-side if it somehow tried to.
An admin may also write the group a short note to the assistant — up to 500 characters, something like "emails from Riverside Primary are about Ada" — that travels alongside the email on every "turn into cards" turn, so the extraction step has context the email text alone might not carry. It is stored on the same row as the address and is never sent anywhere on its own.
In scope: the switch, the address, who is allowed to send to it, receiving and storing a forwarded email as a pending item, its retention, the screens a member uses to view and act on an item, the settings screen the switch and address now live on, and the assistant note. The assistant turn that turns an item's text into cards runs on the member's own session under the rules the assistant's own assessment already covers, and is not re-examined here beyond what reaches it (§3) — out of scope, covered elsewhere: the general assistant-extraction privacy posture, covered by the residency and cloud-inference assessments this register already holds.
A quiet chat row when mail arrives (added 22 September 2026)
The group chat gains one small, centred system row — "New mail arrived in Mail Sifter." — the first time an email lands in a given hour; a second email inside that hour adds no second row. It is a chat message the household reads when it looks, not a notification: nothing is pushed to a lock screen, and nothing changes a chat badge. Tapping the row opens the tool.
The sentence carries nothing from the email. Not the subject, not who sent it, not a filename — the words are fixed and are the same for every group, every time. The row is written by the same server process that stores the item (no member's assistant session is involved), and it has no author: the row's own "who wrote this" column is left empty, because nobody did — a household member did not raise it, and attributing it to whichever admin happened to turn the switch on months earlier would be inventing a somebody who did not act. This is new for this table (every other row in a group's chat is either something a member typed or a change a member made), and the reasoning is in §6.
This is a small addition to what a household is told, not a new place third-party words are held: nothing about the item, its 30-day life, or who may read it changes. See §5's new row for who this reaches and §9 for when this should be re-read.
Dates read from the email, assignees, and posting to chat (added 16 September 2026)
The card a member sees after an item is assessed changed in three ways, following a report from real use of the feature:
- The assistant may now state a date or time it read out of the email, alongside the words the email used ("this Saturday, 12 September at 10am"), so a member can check one against the other. It is told which day the email itself arrived on and works relative dates out from that — never from whatever day the assessment happens to run, which had been producing dates more than a week off the one the email actually meant. Nothing is written to the group's calendar or task list from this. A stated date is shown on the card, editable with the same date and time pickers used everywhere else in the app, and only becomes a real row when a member taps to create it — the same confirm-before-write shape every option on this card already had.
- Each option now carries its own choice of who it is for, shown as the group's members to tick, pre-filled with the assistant's own guess and easy to change or clear before anything is created.
- Creating an option now offers to announce it in the group chat, on by default, with a plain switch to turn it off. Off, a created task or event is still there — it stays a draft a member can share to the chat later from their assistant tab, exactly as it already worked before this change.
None of this moves what the assistant is allowed to read or where it runs — see §3 for what travels and to which region. It changes what the CARD shows and what a member's tap does with it, which is why it is recorded here rather than treated as a plain bug fix.
Addressing the people an email concerns (assessed 18 September 2026; built the same day)
Until this change the card an assessment produced went to the whole household: every active member's attention area raised it. That is the wrong grain for most mail — a dentist's reminder about one adult's appointment does not need to interrupt four people. What is built, as assessed:
- A card about one person defaults to that person's attention, with "Send to group" off. The card says who it is for ("For Brendan"), and the processing member reviews and can change the recipients before it goes anywhere.
- A card that concerns several people is ONE shared card with a seen state per recipient — never independent copies, so two recipients acting at once cannot create the task or the event twice (the same single-winner resolution the household card already has).
- A name the assistant could not match stays with the processing member. Unknown or ambiguous names are never resolved by broadcasting to everybody; the member who has the item open chooses, or nobody is chosen.
- The audience is enforced where the card is read, not where it is drawn. Which members' devices can read a card as theirs is a database read rule, because a client-side filter over a household-readable row would be a privacy claim the database does not keep.
- Recipients — while the card stays targeted — are active adult members only, enforced in the
database. A trigger on the recipients table refuses a child as the recipient of an
INBOX_PROPOSALrow (TGT02), whatever wrote it. This is a property of the recipient list, not of who can eventually read the card. Once a member taps "Send to group", the card's audience widens tohouseholdand it becomes an ordinary group-readable action card — the same row type and the same read rule as any other household card — and a child account's database access is unchanged: nothing refuses that read. What keeps a child from actually seeing it is that a child's account has no Assistant tab to show it in, the same client-side gate that hides the rest of the assistant from them — a conventional property, corrected 18 September 2026 after an earlier draft of this section described it as structural. See §8.
What targeting does NOT do, and the screens must say so honestly: it routes attention, it does not make anything private. The pending item itself — the third party's words — remains readable by every active ADULT member for its 30-day life exactly as §3 describes (a child's account is refused this read by the database as of 19 September 2026, §8), and a task or event created from a card is an ordinary group record every member can see. Choosing one recipient decides who is interrupted; it neither hides the email nor makes the resulting task theirs alone. And no member is ever shown whether another member has seen a card — the seen state exists for the recipient's own badge and for de-duplication, not as a report to the sender; a seen indicator shown to others is the read-receipt shape this app removed for every member and must not re-enter through this door.
The recipient rows and seen state live and die with the card, and the card with the item. The audience model itself — what a recipient row holds, who may read a seen state, why no recipient-scoped row may hold free text, and the retention and erasure rules that follow — is one design shared with the app's other targeted attention surfaces and is assessed in full in our assessment of targeted notices; this feature inherits it rather than defining a second version, and the inheritance is stated here so it is not assumed:
- Deletion follows the card, which follows the item. A recipient row and its seen state cascade from the card; the card cascades from the pending item. So resolving an item, the 30-day expiry sweeping it, or an admin deleting the group removes every recipient row and seen state with it — there is no separate sweep to remember and no orphan to chase. Nothing here extends how long a third party's forwarded words are held: §3's 30-day rule is unchanged and is still the outer bound.
- A member leaving or being erased takes their recipient rows and seen state with their membership, by the same cascade the rest of the app's account erasure uses. A recipient's name is resolved from the roster at render rather than stored as text, so an erasure leaves nothing readable behind.
- The card's content is unchanged by targeting. The assessment, summary and options are the same rows §2 already describes, still scanned before they are written, still closed by schema. Targeting adds identifiers and a per-recipient flag — no new content, no new free text.
As built. A card is raised with an audience of targeted and a list of the members it is
for, in one database transaction, by the member whose device assessed the email; the card's read
rule admits that member and the listed recipients and nobody else in the group — and, since
22 September 2026, the group's owner and admins, who may act on any card from the Mail Sifter
item screen; the Assistant tab still shows a card only to the people it is addressed to (a client
display rule, not a privacy claim, over a row the database already grants). The default list
is the people the assessment's options name, matched against the current roster: one person, or
several on one shared card, or nobody — an unmatched name, and a name two members share, leave
the card with the assessing member. "Send to group" and "change who this is for" are explicit
taps on the card, open to anybody the card is already for, and are the only way its audience
widens. A card addressed to one person does not announce anything to the group chat unless
somebody switches that on. A member who is not an active adult is dropped from the list silently
by the database rather than failing the whole card, and a child's account is refused as a
recipient by a check the database applies whatever wrote the row. Simultaneous action by two
recipients on one shared card resolves to exactly one outcome, as every shared card already
does. No notification is sent for one of these cards: the group's rule that landing mail never
interrupts anybody is unchanged, and a card raised by a model's reading of that mail is not a
promise a person made to themselves.
Which of the new controls the database holds, and which it does not. Structural: the
audience is a read rule on the card, so a member's device cannot see a card addressed elsewhere
by filtering client-side — this is the one the whole change turns on, and it is why "a client
filter cannot turn a household card into a targeted one" is a requirement of the build rather
than a preference; per-recipient seen state readable by its own recipient alone; one shared card
with single-winner resolution, so simultaneous action cannot create the work twice; a trigger on
the recipients table refuses a child as the recipient of an INBOX_PROPOSAL row (TGT02),
whatever wrote it; the cascades above. Conventional, and to be test-pinned before it ships: the
honest visibility sentence on the card and the item screen (§5); the default being one person
with group sharing off; the unknown-name fallback keeping the item with the processing member
instead of broadcasting; the extension of the standing feedback-feature source scan over these
screens; and — corrected 19 September 2026, and now split in two rather than one blanket claim.
Since 19 September 2026, a child's account is refused a read of the pending item and the
address BY THE DATABASE, not merely kept from them by an absent tool: group_inbox_items'
SELECT and UPDATE policies and group_inbound_addresses' SELECT policy carry a RESTRICTIVE
not is_child_account(auth.uid()) predicate, ANDed with the existing permissive ones, so an
adult member's read is unchanged and a same-group child gets zero rows from either table
whatever wrote the row asking — this is now structural, for every CLIENT role (a SECURITY
DEFINER RPC or a service-role read is not subject to a restrictive policy, which is why
claim_inbox_assessment still carries its own child refusal). The household-shared card is
untouched by that change and stays conventional: once "Send to group" widens its audience,
the card is an ordinary group-readable action card with no age check on its read rule, and a
child does not see it only because a child's account has no Assistant tab to show it in — the
same client-side gate as before. The active-adult-recipient rule is therefore: structural for
the item and the address (added 19 September 2026); structural for the recipient list while a
card stays targeted (TGT02); and conventional only for the shared card once it has been sent to
the household. See §8.
Jev judges relevance and audience (assessed 21 September 2026; built the same day)
What changes. On the automatic assessment turn, for every group that uses Mail Sifter
(amended 4 October 2026; the next paragraph), a SECOND model call goes to TypeSafe's Jev
after the Gemini call that generates the options. Jev is a classifier: it reads the redacted email, the redacted note and Gemini's
options, and answers typed questions with probabilities — "is this something the household would
act on?" and, for each option and each member placeholder, "is this for Member A?". Code
thresholds those answers into the SAME two fields the assessment already carried: relevance
and each option's assignee_hint. Jev writes no title, no date, no summary and no sentence;
Gemini's generated text stands. Nothing new is shown on a card; what changes is which model
decided the two facts the card already stated.
Why every group, and what excludes an email instead (amended 4 October 2026). As first
assessed on 21 September 2026, the second opinion ran for a group at global_all and nowhere
else: the assessment runs on the insight_summary node, which the ladder admitted to a global
provider only at that level (globalNodesFor), and Jev was gated on the identical isGlobal the
Gemini call used. The amendment at the top of this document moved every group's assessment to
Vertex global, and TypeSafe's second judgment went with it, so it now runs for every group
that uses Mail Sifter, whichever privacy level the group is at. The exclusion is no longer the
privacy level but the health-vocabulary pin
(carriesHealthVocabulary(inboundEmailPinText(...))) — an email about a child's medicine stays
with Gemini for every group. Jev is handed the same name map either way, so the state it reads is
in Member A / Baby 1 placeholder space; where it is skipped, the usage event records
ineligible for the denominator and nothing else.
Where it runs and under what terms. TypeSafe is hosted in the United States (privacy policy effective 19 November 2025: "The Services are hosted in the United States"). The same policy states "We will not train or fine tune any artificial intelligence or machine learning models on your prompts or other Input" and "We will not disclose any Input to a third party other than our service providers", which is what the Global consent copy's "nothing is used to train models" line requires of a provider. Retention is not a fixed window — "for as long as reasonably necessary to provide you with the Services" — and a zero-data-retention term is an enterprise option we do not hold. That is a weaker retention posture than Resend's stated 30 days and is recorded in §8 as accepted residual risk, not resolved.
A second global provider is a change to what the consent named. The Global copy says "any of
the provider's regions", singular, and every overseas_processing consent row to date was given
under that sentence. The Privacy screen's copy and the privacy policy (v1.11) are amended in the
same change to "our providers' regions", so a group choosing Global from now on reads the
accurate sentence. Groups
already at global_all were consented to overseas processing by a global provider with names
replaced; this adds a second such provider for one narrow judgment under the same terms and
the same name replacement. Whether that is within the consent given or needs a fresh
confirmation is an owner decision this document records as OPEN — the conservative path is a
one-time chat notice to the groups currently at global_all naming the change, which the
existing privacy_level system-row mechanism can carry.
Fallback is structural, not a promise. The Gemini assessment is computed first and in full; Jev can only replace two fields of it. No key, a rate limit, an outage, a slow answer (6s) or a reply of the wrong shape all leave the Gemini answer untouched — a runnable check asserts each of those against a stubbed service. The member cannot tell which model judged, and does not need to.
What is measured. One JSON line per assessment (typesafe_usage: outcome used /
fallback / ineligible, a reason, token counts, latency; no group id, no user id, no text),
and a row in the platform spend ledger under provider typesafe, so the daily report shows the
two global providers apart. The thresholds (0.5 relevance, 0.6 audience) are
starting points from the model card, not measurements on this app's mail; the review trigger
below names the eval that would make them measurements.
Attachment bytes, not just names (assessed and built 21 September 2026)
Until this change, an attachment was a NAME on the item's row — the sender's chosen filename, and nothing else. This reverses that for a closed list of file types, under fixed caps, and only AFTER the item is already stored:
- The webhook lists the email's attachments at Resend, and streams the allowlisted ones into a
private bucket, once
store_group_inbox_itemhas already answeredstored: true. A refused email (policy, cap, duplicate, auth double-fail) costs no download — the identical ordering the body fetch already keeps, extended to this new step. - Allowlist and caps are decided by a pure, unit-tested function, not by the database.
text/calendar,application/ics,application/pdf,image/jpeg,image/png,image/webp,image/heic,text/plain; 10 MB per file, 25 MB per item, 10 files per item, in list order. An inline part is refused unless it is a calendar invite (an invite is usually sent inline). A file that fails a rule gets a row recording WHY (skipped_type/skipped_size/skipped_count/failed) and no object — the filename and the reason are visible to the group; the bytes are not fetched. - Best effort, and the webhook still answers 200 either way. A failed list, download or
upload writes a
failedrow (or nothing, if even the list failed) rather than turning a successfully stored item into a 503 that would make Resend redeliver an emailstore_group_inbox_itemwould then refuse as a duplicate — which never retries the files anyway. Nothing here is logged beyond counts and outcomes. - The object's name carries no filename.
inbox/<group_id>/<item_id>/<attachment_id>— the sender's chosen filename is free text and lives in the row, not the path, the same reasoning the photo wall and the avatars bucket already apply to their own object names. - Bucket access is by path, exactly like the photos and avatars buckets, PLUS a child refusal
those two lack.
can_access_inbox_attachment_objectchecks active, standing-group membership on the group id already in the path, and additionally refuses a child's account outright — the photos function has no such check; this one does, from the start, because attachments here can carry more than a photograph (a PDF is a document, not necessarily a picture of food or a family). - Deletion is tombstone + sweep, the same mechanism
sweep-photo-copiesuses, because a database trigger cannot delete a storage object. ABEFORE DELETEtrigger on the attachment row, and the item's own pending→resolved transition (a second,AFTER UPDATEtrigger), both produce a tombstone;sweep-inbox-attachments(hourly, pg_cron → pg_net, its own Vault token) removes the object and then stamps the tombstone. Because Postgres fires a row-levelBEFORE DELETEtrigger on a CASCADED delete too, the 30-day item sweep, an admin deleting the group, and an account erasure all tombstone every attachment object without any extra clause anywhere. - Plaintext on our server, exactly like the body. No sealing in this design — the copy and this document say so; see §8 for why that is accepted rather than deferred.
- No client write path, at the time this was written. The row was service-role INSERT only (the webhook); a client could only ever READ its group's own rows. That changed the following day — see "A second way in: the share sheet" immediately below, which is exactly the future change this bullet anticipated, built.
A second way in: the share sheet (added 22 September 2026)
Until now the only way mail reached this feature was the address. From this date a member can also choose "Share to GroupApp" from any other app on their phone — a browser, a photo gallery, a file manager — and send a page, a photo or a file straight into one of their groups, with no address involved at all.
The authority is completely different, and that difference is the whole design. An emailed item's authority is the address: a token nobody but the group is meant to hold, checked by our mail-receiving provider before anything is stored. A SHARED item's authority is the member's own session: they choose the group on their own screen, signed in, and the row is written by a function that checks their membership directly — nothing from the email path (the token, who may send, the automated sender check, fetching from the mail provider) applies to a share, and nothing about a share is reused to authorise an email. What the two paths DO share, from the point the item exists onward, is everything downstream: the same table, the same five statuses, the same one-time assessment by the next member who opens the app, the same household cards, the same daily cap per group, and the same 30-day life.
- The operating system's own share sheet is deliberately kept ignorant. The small piece of our app that the phone's share sheet talks to holds no sign-in of its own and makes no request to anywhere — it only captures whatever was shared into a small, private handoff area the operating system provides and then opens the rest of the app. Every decision from that point — which group, whether to add a note, whether to actually send it — happens on a screen the member sees, signed in, exactly like anything else they do in the app.
- One group, chosen on screen, every time. A share never reaches more than one group's inbox, and it is never assumed to go anywhere until the member confirms it — the confirm screen shows what was shared (the text, a preview of any file) and asks which group, defaulting to whichever one the member currently has open.
- A stated file cap applies here too. The same eight file types, the same 10 MB per file, 25 MB per item and ten-files-per-item limits already described above for an emailed attachment apply identically to a shared file — the confirm screen tells a member plainly when a file will not be kept, and why.
- A member may add one short note before sending, read by their own assistant alongside whatever was shared, exactly like the note an admin can already leave for emailed mail (§1's "assessed on arrival" section) — the same rule about it being data rather than an instruction applies here too.
- The group finds out the same way it finds out about an email arriving — nobody is notified; the item simply appears, waiting, the next time somebody opens the tool.
- Not offered to a child's account. A child sees no "Share to GroupApp" option and, if a request to share reached the server anyway, it is refused outright.
- A daily cap that already existed now counts BOTH kinds of arrival together. A group that already had fifty items land today — emailed, shared, or a mix of both — cannot take a fifty-first of either kind until the day rolls over.
- What the confirm screen says (shortened 10 October 2026). Above the button, always shown: "Every adult in the group you choose can read it, and the assistant sorts it using Google’s AI." Under "How it’s handled", one tap away and before the button: "It’s stored on our server and deleted once it’s dealt with, or after 30 days. It never goes through email." Who can read it and who receives it (shown) are the choice being made; where it is kept, how long, and that it never goes through email (one tap) are on the same screen before anything is sent. Google's AI was not named on this screen before; it is now, because sorting a share sends it to the same model as any other assistant request. We accept the shorter screen under our principle of being useful first, with informed opt-in: the deciding line is always in view and no fact was removed.
Calendar invitations become event options, read by a parser, never by a model (assessed and built 22 September 2026)
A stored calendar file — the kind a school, a clinic or an invitation service attaches to its mail — used to be just another stored attachment: visible on the item, downloadable, otherwise untouched. This adds one thing, on the member's own device, at the same moment that device already reads the email itself:
- The date and time on an option built this way come from the file's own start-time field, on the device, never from a model. A date read out of a sentence can be read wrong, which this document already records as the worst mistake this feature has made in real use (see "Dates read from the email" above); a calendar file's own start field cannot be misread the same way, because there is no sentence to parse — only a structured value to copy. The card marks such an option "From the attached calendar file" so a member never mistakes it for the assistant's own guess, and it still creates nothing until that member taps it, the same confirm-before-write rule every option on this card already has.
- These options come first, and are never the ones trimmed. If the file's own events and a model's separate suggestions together would make the card longer than it is allowed to be, it is the model's list that is shortened, never the file's.
- The file's events are also handed to a model, as plain rendered lines in their own fenced region, on the very same turn that assesses the email or turns it into cards — with an instruction, stated plainly and outside that fenced region, that the listed events are already offered and should not be suggested again. This is deliberately a second, independent check on top of the first: the device also compares a model's own suggestion against the file's dates directly and quietly drops one that plainly repeats it, so the household is not shown the same invitation twice.
- A cancelled event in the file is never offered as an option — nothing is proposed for something the file itself says is off — though its words still reach the model on the same turn, so a summary can still say a cancellation happened.
- Only the first date of a repeating event is ever offered, worded to say the event repeats; this feature never expands a whole series of future dates into separate options.
- A time zone the device does not recognise — an older calendar program can write one in a form this app cannot look up — is shown as the file wrote it, in the group's own zone, with a plain note that the zone could not be confirmed, rather than a silently wrong conversion.
- The event's own title reaches the card exactly as the file wrote it — a third party's own words, shown verbatim, the same as a forwarder's own subject line already is, and not run through the same check a model's own sentences are (see the new row in §5).
- Turning an email into cards by hand still sends the file's words to a model in the same fenced region, but does not build these deterministic options itself. The one automatic pass every item already gets is where the options are built; the hand path stops at handing the file's own words to the model on that turn — and on that turn the model is told to read the calendar's text as part of the email's own content, while on the automatic pass it is told the events are already proposed and must not be repeated (the two sentences are chosen by a flag the device sets only when it has built the options itself). Recorded here as a known asymmetry rather than closed silently — a difference worth revisiting only if real use shows the hand path's model misreading a file's dates the way a sentence once was.
PDF attachments are read by the assistant (assessed and built 22 September 2026)
A stored PDF attachment — a camp itinerary, a permission slip scanned to a document rather than typed into the email — used to be just another stored attachment: visible on the item, downloadable, otherwise untouched, exactly as a calendar file was before the change above. This extends the same idea to plain text extracted from a PDF, with one structural difference from the calendar case: nobody's device in this app can read a PDF's text today, so the extraction has to happen somewhere, and the "somewhere" is our own server rather than the household's own phone.
- The text is extracted on our server, not on a member's device, and only under that member's own read rule. Our server downloads the file using the SAME signed access a member's own device already has when they tap "View" on the item screen — the request is authorised as that member, not by any elevated access of our own, so a child's account or somebody who has left the group gets nothing, the same as any other attempt to read the file. The bytes are read once, the text is kept only for the length of that one turn, and the bytes themselves are never modified, copied elsewhere, or kept beyond the length of the request.
- This is a genuine difference from the calendar case, and it is why this is its own dated entry rather than folded into that one. A calendar file's dates are read by a small parser written for this app and run on the member's own phone; a PDF's text is extracted by a general-purpose library, run on our server, because the equivalent on-device capability does not exist here. The household's mail still never reaches a THIRD PARTY because of this — the extraction happens on the same server that already stores the file — but it is a server-side processing step this feature did not previously have, and it is recorded as such.
- Capped in length, page count and how many files are read on one turn. The first twenty pages of a file are read; the extracted text is capped in characters, per file and across every attachment on the turn combined (the combined cap covers a calendar file's own text too, exactly as before); at most two PDFs are read on any one turn. A scanned document with no text layer at all contributes a fixed line saying so, never a guess at what an image might say — this step reads text a PDF already contains. Pictures, attached, inside an email or shared from a phone, are read by a separate step, assessed on 24 October 2026 (see "Pictures in Mail Sifter").
- The extracted text is handed to the model on the SAME turn the email itself already reaches it on, in its own fenced region, exactly like a calendar file's own words already are. It is told, outside that fenced region, that this text is part of the email's own content and may produce options the way the body itself does — and that a date found in it is read against the same received-date anchor a date in the body already is.
- A per-group switch, admin-only, on by default, lets a household stop this without turning off anything else. Turning it off does not touch the file itself — it is still stored, still shown on the item, still viewable by tapping it — it only stops that file's text from ever being extracted and sent onward. The switch narrows what a household already disclosed by turning Mail Sifter on and storing the attachment in the first place; it does not, on its own, decide whether a group receives and keeps PDF attachments at all, which the earlier attachment-storage change already covers.
Encrypted as it arrives: the group inbox keypair (assessed and built 30 September 2026; not yet released)
Everything above describes what arrives. This describes what we will keep once this reaches a group, and it is the Mail Sifter part of our wider change to seal group content (our assessment "Content encryption, second stage", §3.6). It has been built and merged, matching the design below, but it takes effect only once our next database release ships and a group's phones have updated to the app version built alongside it; until then, and for anything sent before that point, mail is stored exactly as the rest of this document describes it today. Email is still email: it passes through our email provider, Resend, in Japan, and through our mail server's memory, in the form the sender wrote it. Nothing here changes that, and the copy says so. What will change is that, from the moment a group is set up for it after release, our database will no longer hold the words.
- The keypair. Each version of a group's key gets its own inbox keypair. The public half is stored where our mail server can read it; the private half is sealed under the group's server-openable key, so the group's phones can open it, and so can our assistant server inside a member's own request, through the same single reader that opens event notes. An owner's or admin's phone makes the keypair — when Mail Sifter is turned on, and otherwise the next time the app comes to the front after this version arrives or after the group's key changes. In a Standard group it waits until our assistant server holds that version's key (added 6 October 2026), so the assistant can open what it is asked to sort. The first keypair published for a version is kept; a later attempt is refused, so items already sealed to it keep opening.
- An email arriving. After the signature and the sender rule are checked exactly as before, our mail server makes a fresh key for this one item, encrypts the subject, body, sender's address and name, attachment names, and each stored attachment's bytes with it — each bound to the item and the group, so it cannot be moved to another item or group and still open — then seals that key to the public half, stores only the ciphertext, and forgets the rest. It can lock an item and cannot open one. The item's plaintext columns hold fixed sentences instead ("Update GroupApp to read this email"), which is what a version of the app from before this change shows.
- Until a group is set up. A group whose owner or admin has not yet opened Mail Sifter on an up-to-date app has no keypair, and neither does a Standard group whose server copy of the key has not been written yet; its mail is stored as it was sent, as before. Mail that arrived before a group was set up stays as it was sent until it is dealt with or reaches its 30 days. The settings screen and the privacy policy both say this, conditionally, rather than claiming every email is encrypted. On the settings screen, since 10 October 2026, the whole statement opens under "How it’s handled", one tap away beside the sentence about our email provider, which is always shown with the switch; the encryption claim and its limits move together. The same day its sentence about our assistant server was corrected: it said the server opens an email "inside a request a member’s app makes", which stopped being the only way once our server began sorting mail as it arrives. It now says our assistant server "can still open an email to sort it or turn it into cards".
- A share. Something shared into Mail Sifter from another app is encrypted on the phone that shares it, to the same public half, before it leaves.
- Reading an item. A phone fetches the ciphertext and opens it itself. There is no route that answers an item id with words. A phone that has not yet been given the group's key shows the item as locked and says why.
- The assessment. The assessment turn no longer carries the email from the phone: the member's app names the item, and our assistant server fetches it with that member's own permissions and opens it through its one reader — which writes its audit record before any key is released — and reads attached PDFs the same way. The assessment it returns is then sealed on the phone, field by field: the summary, the forwarder's recognised instruction, and each option's title, timing in words and suggested people are sealed; the relevance, each option's kind, date, time and source stay readable, so the database can keep refusing an option that is not a task or an event. An app version from before this change is no longer allowed to claim a sealed item for assessment, because it could only send the fixed sentence.
- The note to the assistant is sealed under the group's server-openable key, like event notes, and read by our assistant server inside a member's request rather than sent from the phone. An owner's or admin's phone reseals a note written before this change.
- Resolution and the 30 days are unchanged: resolving an item removes its body (both copies) and its attached files at once, and the whole item goes after 30 days. The item's own sealed key stays until then, so a resolved item's subject still shows, as it did before.
- Older app versions see that an email arrived, when, and a sentence asking them to update; they cannot read it, turn it into cards, or assess it. We chose this over keeping plaintext until every member has updated, because the alternative keeps every group's mail readable on our servers for as long as any one member does not update.
Sorting that finishes, and a record of each try (assessed and built 1 October 2026; not yet released)
On 1 October 2026 a member reported emails that sat waiting to be sorted for a long time. Three causes were confirmed in our own code: an email whose summary used a word we refuse to say about a person was retried, and billed, every ten minutes; leaving the Mail Sifter screen stopped the sorting part-way, after our server had already done the work, and the email then could not be tried again for ten minutes, even by the member whose phone had started it; and the screen showed "working" whatever was actually happening. The changes:
- A claim is short and fenced. A phone that starts sorting an email holds it for three minutes (longer only while it is still working), with a single-use token. Nobody else's phone may take it while it is held, including another phone of the same member, so the same email is never sorted, or paid for, twice. Every write about the email carries the token, so a slow, abandoned attempt cannot overwrite a newer one. A phone that gives up lets go at once, so the email can be tried again straight away.
- A refusal is final. When the assistant's answer is refused, or comes back unusable twice, the email is marked as not sorted, with a plain sentence saying so, instead of being retried. That is not a judgement that the email does not matter: such an email is listed under "Needs a person", open, never beside the emails the assistant judged not worth acting on; the member can still turn it into cards themselves; and a calendar file attached to it still becomes a card.
- What we refuse is a judgement about a person, not an email's ordinary words (changed the same day, after review). The check used to be the same list of words we keep out of our own copy about a member's plans — "points", "only", "again", "late", "fair" and others — and those are ordinary facts in an email: frequent flyer points, a late fee, an overdue invoice, "only 3 seats left", a school fair. An email that said "use points" was refused outright. The check now looks for the assistant describing a PERSON — the sender, the group, or anybody the email names — with a verdict: characterising them, blaming them, urging them, saying what they "should have" done, or pinning lateness or failure on them ("you still haven't paid"). It still covers every line a member is shown: the summary, any recognised "Hey GroupApp" line, and each option's title and who it seems to be for. When it finds one, the assistant is asked once more, told which lines and which words, to state the email's facts without judging anyone; if the second answer still judges somebody, the refusal above applies. It is still a floor, not a proof: a sentence can judge somebody without any word the check knows.
- The card and the result are saved together. The household card and the recorded result for an email are now written in one step, under the same claim. Before, a phone wrote the card and then the result; if the second write was lost and a later try produced different suggestions, the email and its card could describe different things. Now a card nobody has acted on is replaced by the newer result (or removed, if the newer result is that the email is not worth acting on), and a card somebody has already started acting on is kept, with the email recorded as that card describes. A phone whose claim has lapsed and been taken writes neither. Every result is also held to the same size limits whichever way it was produced, so two full calendar files can no longer produce a result too large to save.
- The screen says what is happening: sorting on this phone now, being sorted on another phone, or not sorted yet, with a button to sort it now.
- A record of each try. A new record notes, for each attempt, which email it was about, which step it reached (claiming it, asking the assistant, writing the card, saving the result), a short code for what happened (for example "claimed", "released", "malformed" or "failed"), and when. It holds no words from the email, the assistant's answer, or anybody's name, and no record of which member's phone made the attempt. Only the group's owners and admins can read it, to see whether an email is stuck and why; it is never shown as a count or a figure about any member. Nothing writes it except the sorting steps themselves. Each row is deleted with its email, and every row is deleted 30 days after it was written, by a nightly job that ships with it.
- Creating cards from a household card is held by the database, not only by the phone. When a member taps "Create selected", each task or event is created under an identifier the database hands out only while that member's phone still holds the card and the email is still waiting, and the database checks both again at the moment the task or event is written. A phone whose hold was taken over, or one racing somebody else dealing with the email in Mail Sifter, creates nothing more, and no option is created twice. The record behind this holds the card, which option, the hold's token, the member's id and two times; no words from the email or the card. It is not readable by any member, and it is deleted with the card or the member. An older version of the app does not use these identifiers, so a member still on one is not held this way until they update.
- The sender shown for an email with no name now reads "Forwarded email" rather than "Someone". We do not name a member from the address the email came from: that address is a claim the sending mail server makes, not proof of who forwarded it.
Sorted as it arrives, by our server, for groups that choose it (assessed 9 October 2026; built the same day, not yet released)
What changes. Sort emails as they arrive, in Mail Sifter's settings, is ON for every group, including every group that already uses Mail Sifter (owner decision, 10 October 2026: "we can't trust users to find it and turn it on"). An owner or admin may turn it off. While it is on:
- About once a minute the database checks, without leaving the database, whether any email in a group with the switch on is waiting to be sorted. If one is, it knocks on our assistant server. The knock carries nothing — no email, no group, no id.
- Our assistant server then asks a small service of ours that holds the database's elevated access, proving who it is with a credential Google signs for our server alone. That service hands over up to three waiting emails, still encrypted, with what is needed to open them, and writes a record that our server is about to use the group's key — before it hands anything over.
- Our server opens each email, reads any calendar file and (if the group allows it) PDF attached to it, and asks the same model, in the same way, with the same rules, as a member's phone does today: the same fences, the same refusal to judge a person, the same second opinion from TypeSafe with names replaced and never for an email with health words.
- It records the result and, when something is worth doing, raises the same card, addressed to the people the email names (or, if it names nobody we can match, the group's owners and admins). The card's words are encrypted before they are stored. If our server cannot encrypt them, it stores nothing and leaves the email for the next phone, exactly as today. (1 November 2026) Once switched on, cards also carry a short title the model writes from the same email or share; it is encrypted with the card's other words and never stored with the item.
Who pays. No person. Each group has a weekly amount for this (A$0.50 unless we agree more). Each email reserves a small amount before any model is asked and settles the real cost after, and our platform-wide ceilings still count it. When the week's amount is used up, nothing breaks: new mail waits for a member's phone, as it does today, and an owner or admin sees one line saying so with a Request more button. The request carries no words; we see it in our daily report and may raise the amount for that group.
What does not change. The address, who may send to it, the 30-day limit, the body being deleted when an email is dealt with, a child's account reading nothing of it, the card's options being closed to tasks and events, and Turn into cards. A Device-only group is never sorted by our server: the code refuses it before anything is read, and the database will not hand it over. Each email is tried at most twice; after that, or for any email our server cannot open, a phone sorts it as before. A phone leaves an email our server is due to sort alone for ten minutes, so the same email is never paid for twice.
On by default, and why that is accepted (amended 10 October 2026). Members were told that sorting happens when somebody opens the app, on that person's own allowance. Sorting with nobody present, paid by the group, is a different bargain even though the model, its location, its rules and the email it reads are the same. The 9 October design therefore made it a fresh, consent-class choice, off for every group. We reversed that the next day: a switch nobody finds is a feature nobody gets, and the processing is the one each group already accepted when it turned Mail Sifter on — the same email, the same providers, the same rules — only sooner and paid by the group. So it is an opt-out group setting: on by default, only an owner or admin can turn it off or back on, the group is told in its chat when they do, and there is no consent record and no twelve-month lapse (a lapse would only ever turn a default off). "Informed" is carried by the privacy policy (v3.4), whose what-changed sheet every member sees once, and by the sentence beside the switch, which says whether this group has it on or off and who can change it (shown). That it uses the same assistant and rules as a phone, and the group's weekly amount, are one tap away under it (since 10 October 2026). That is weaker than an opt-in under Useful First, With Informed Opt-In, and it is recorded as an accepted residual in §8. What does not move: a Device-only group is never sorted by our server, and nothing about children's accounts changes — a child's account still reads no email and is never a card's recipient.
The notification proposed alongside it ("tell me when Mail Sifter has suggestions for me") is the second half of this change, assessed with it and built the same day: per member, on by default since our decision of 10 October (a suggestion nobody knows about helps nobody), turned off in You → Notifications beside invitation notifications, where Mail Sifter's settings link (since 21 October 2026; it was in both Mail Sifter's settings and Settings → Advanced before). It is sent only after a card our server raised, only to the adults that card is for who have not turned it off, once per card and device; it names the group and says "Mail Sifter has suggestions for you." — never the sender, the subject or anything the email says. It is a preference, not a consent: nothing new leaves, it only decides whether to interrupt them. A child's account is never a card's recipient, so it is never sent this.
Built, not released: a deadline the email states becomes the task's own due date (assessed 10 October 2026; built 11 October 2026)
An assessment already reads a date and time out of an email when the email states one, shows it on the card beside the words the email used, and lets a member change it with the same pickers the rest of the app uses. What a tap does with it differs by the kind of option:
- An event option writes that date and time as the event's own start, as it always has. An event's start is readable by our server — that is how a calendar, a reminder and the daily brief work at all — and nothing about that changes here.
- A task option writes no deadline anywhere. The date survives only inside the sentence that records where the task came from ("From a forwarded email … by Thursday"), and a task's notes are encrypted on the phone that writes them. The task has no deadline, so nothing can remind anybody about it and it never shows as late.
The planned change gives a task option the same date and time control the event option has, and writes what the member confirms to the task's own due date and due time — the ordinary columns a task typed by hand already uses, which are not encrypted because our server works a reminder's time out of them and decides whether a task is overdue. The due-time column is new work of its own, assessed with the task changes that introduce it; what this document assesses is one thing only: a deadline stated in a THIRD PARTY's email reaching those columns.
Said plainly, this is a small disclosure change, and it is a change. A deadline somebody else wrote in an email becomes readable metadata on our server, where today it is readable only on the group's own phones. It is a date and a time, never words. Nothing is guessed: an email that states no deadline leaves the field empty for a member to fill in, exactly as the card already behaves for an event. The email's own wording stays in the notes, encrypted as before. And nothing is written until a member taps to create the task.
As built, 11 October 2026 — no release carries it. Everything above holds, with three things said exactly:
- Only a date the email stated. A task option offers the assistant's own reading of a stated date and time and nothing else. An event option falls back to reading the email's free words ("this Saturday") because an event with no date cannot be created at all; a task needs no deadline, so it buys nothing with a guess and a wrong deadline now costs something a wrong note never did. An email that stated none leaves the pickers empty for the member to fill in, and a task with no deadline is still perfectly creatable.
- The date and the hour are written; the reminder is always "off". The tap writes the task's
due_date, itsdue_timeand its reminder choice through the same code the task sheet uses, so the two screens cannot mean different things by the same three columns. The reminder choice is always "off": nothing on this card offers a reminder, because a reminder set from a third party's email is a choice a member should make, not a default a card picks for them. A member who wants one sets it on the task's own sheet, where the choice and its own sentence already live. (The write asks the database outright whether it has the due-time column, rather than learning it from a refusal — a refusal naming it cannot be told apart from one naming a sealed column, and answering that by dropping the sealed ones would store the group's task words unsealed.) - Nothing else moved. The email's own words still travel verbatim into the task's notes, sealed on the phone that writes them; the create is still fenced by the database; and both sorting paths — a member's phone and our server on arrival — produce the same card, because both carry the stated date onto the card and both create the task through the same code.
Built, not released: Mail Sifter offers a repeating arrangement an email describes (assessed 10 October 2026; built 11 October 2026)
Groups are getting routines — a repeating arrangement, with whose turn it is, kept apart from one-off tasks. Mail about a group is full of them: "bin collection moves to Wednesdays from 1 November", "library bag every Thursday". Before this, the first of those produced at best one task on one date, and the arrangement itself was left for somebody to change by hand. What is built, on both sorting paths — a member's own phone, and our server's sorting on arrival:
- One more question during the assessment: is this a repeating arrangement, or a change to one? It is a yes/no answer, asked of Jev on the same call and under the same rules as the two answers Jev already gives: names replaced, and never for an email carrying health words. Unlike those two, there is no answer from the generating model underneath it to fall back on — so when Jev does not answer, no routine option is offered at all (below).
- The schedule is read from the email's own words, by code, and never invented. "Wednesdays from 1 November" becomes a weekly day and a start date; an email that states no schedule produces no option at all.
- Which routine it concerns is a choice between the routines the group already has. Their titles travel with the redacted email to Jev, with names replaced the same way every other string on this path is, and "none of these" is always one of the choices. "None of these", or an answer that does not stand clear, offers a NEW routine rather than a change to an existing one.
- One new option on the card, applied only when a member taps it. The option says what it would do, in the group's own words ("Bins out: Tuesday → Wednesday from 1 Nov"), and the tap is what creates or changes the routine. The assessment itself changes nothing, on either path.
- When Jev does not answer, or the email carries health words, no routine option is offered and the email is sorted exactly as it is today. There is no code-only guess at a repeating arrangement.
A child's account is not involved: it never triggers an assessment, is never a card's recipient, and reads neither the email nor the address. A Device-only group is not involved either — it cannot receive forwarded mail at all, so there is nothing here for it to do, which is a stronger exclusion than a switch.
What is genuinely new, and the honest cost of it. Two things:
The group's own records leave the group on this path for the first time. Everything this document has described reaching a model so far is the forwarded email, its attachments, and the group's own note about what to expect from mail. A routine title is the group's writing about its own arrangements, and a title can name a person ("Ada's lunchbox"). Names are replaced before anything is sent, which is what already happens to every member name on this path — but a replacement is a word match, not a guarantee. §5 carries it as a risk and §8 as a residual.
The card gains an option that is neither a task nor an event. §5 and §6 both rest on an option's kind being closed to those two words: it is the reason a hostile "Hey GroupApp" line written inside a forwarded email has nothing else to ask for. A routine option changes a STANDING arrangement rather than adding one row, so the consequence of a member tapping without reading is larger than it was, and §§5, 6 and 8 say so.
What was built did NOT widen that list (11 October 2026). The assessment above expected a third word; the implementation instead gives the routine option its own separate field on the card, which no model writes at all — it is assembled by our code out of Jev's two answers and our code's own reading of the email. The list of option kinds is still exactly two words long, so the defence this document leans on is unchanged rather than one word weaker, and there is nothing a forwarder could write inside an email that would produce a routine option.
What is narrower than this assessment allowed for (11 October 2026). Four things, each reducing what was accepted rather than extending it:
- The closed list of option kinds did not widen, as just described.
- A routine option is never stored on the email's own record. It travels on the reply and onto the card, and nowhere else. One visible consequence: "Make cards anyway" on an email the assistant judged unlikely offers no routine option, because the stored record does not carry one. Nothing is lost that a member can see on the card they were offered.
- Only two kinds of schedule are read: every day, and named days of the week. "Fortnightly", "monthly" and "a number of times a week" are not read at all. Those are measured from a first date, mail of this kind rarely states one, and picking a first date would be inventing exactly what the second bullet above forbids.
- No reminder is ever written. Exactly as for a task's stated deadline above: the household's existing reminder choice on that routine is left untouched, and a reminder from a third party's email is a choice a member makes on the routine's own sheet.
And one thing is narrower on OUR SERVER's sorting path only. It offers to set up a NEW routine, and does not yet offer to CHANGE an existing one, because the leased record our server reads a group's words from does not yet carry the group's routine titles. So on that path no routine title leaves the group at all today, and the "group's own records leave the group" cost named above is, for now, a cost of the PHONE path alone. A member's own phone offers both halves. This is a gap in the build, not a change to the assessment: when the leased record carries the titles, the server path becomes exactly what is assessed above, under the same name replacement, the same health exclusion and the same cap.
Pictures in Mail Sifter (assessed 24 October 2026, PIA-008; built, off behind switches)
The full assessment is PIA-008, approved on 24 October 2026 with conditions S1–S21 and decisions F1–F9. In short:
- What is new. Our assistant server reads the words in pictures: ones attached to an email, ones carried inside its message (now stored, at most six an email, after every real attachment), and screenshots shared from a phone. A picture linked from the web is never fetched. The words go into the assessment as the email's own content, fenced like a PDF's text.
- Where. Gemini 4 Argon at Vertex
global(from the release after 31 October 2026; before it, Gemini 3.8 Flash), falling back on capacity only to 3.8 Flash and then 3.7 Flash, the same processor, project and terms as every other Mail Sifter call (cloud-inference §12, amendment of 31 October). The call carries the re-encoded picture and a fixed instruction, nothing else: no names, note, sender, subject or body. It asks for text only and never a description of a person; a person is[photo]. TypeSafe never receives a picture; it may receive the words, names replaced, unless they carry health words. - Who decides. A share is the member's choice on the confirm screen (marked only when the app
version that shows the words sent it). Email pictures need the group's admin switch "Read
pictures in emails": off for groups that had Mail Sifter before, on for a group's first setup
after the feature is switched on, and never changed by a later setup. Only email from a member
or a named sender is read, and only when that address's own domain vouched for the message (a
DMARC pass, or a DKIM signature aligned with the From domain, as our receiving server recorded
it); an SPF pass alone does not count. Never one let in by "accept anyone". A 16- or 17-year-old's picture is read only after their own AI yes, checked
again before reading. The same holds for the words of anything a 16- or 17-year-old shares, or
an email a member under 18 forwards (founder decision, 24 October 2026): sorted with AI only
after their own yes. A forwarder is recognised only when the email comes from the address their
GroupApp account uses. Turning the switch off stops any picture not yet read; turning it on never
reads an email that arrived while it was off. Under-16s
and Device-only groups: never. Every rule is decided when the item arrives and checked again
before reading (
inbox_pictures_readable), so nothing that arrived before is read. - What is kept. The words, credentials masked, sealed under the item's key on the picture's row, deleted with it (resolve, or 30 days). Location and camera details are removed from emailed JPEG, PNG and WebP pictures before they are stored, and every picture is re-encoded before the model sees it. An emailed HEIC is stored as sent and is not read (no decoder on our server).
- Spend. The group's weekly amount is A$1.00; each picture call reserves first; at most four pictures are read an item, two a call; tiny, animated and duplicate pictures are skipped by code.
- Off until the words are on phones. Two platform switches (email, shares) stay off until the policy version after v3.13 and the confirm and switch wording ship (F8).
- Residual risks accepted (R1–R6). People in screenshots are told nothing and their words and faces reach Google overseas; children's faces and names can too, and pixels cannot be pseudonymised; a prompt Google's safety classifiers flag, a picture included, may be logged for up to 90 days and reviewed by Google staff, and Gemini's cache holds requests for up to 24 hours, for Argon as for Flash, with no abuse-monitoring exception in place, so we make no zero-retention claim (restated 31 October 2026 from Security's ruling on Argon); the health word list can miss over an imperfect transcript; every adult member can see each stored picture for up to 30 days; with the email switch on, a school's or club's pictures of other families' children are read with no member choosing that picture.
The picture step gains a second caller (28 October 2026, HQ PIA-011; built, switched off)
The step that reads the words in Mail Sifter's pictures is now also used when a member attaches a
photo to a message to the assistant. Nothing about it changes for Mail Sifter: the same
re-encoding, the same fixed instruction (words only, never a description of a person), at most
four pictures and two a call, the same models at Vertex global, no tools, and an automated check
that the assistant's request matches the one it pins for Mail Sifter. The assistant's use has its
own gates, daily picture cap, guardrail and spend at the assistant's surface, and keeps nothing on
our side; Mail Sifter's switches, admin setting and group amount do not apply to it, and it does
not touch Mail Sifter's items. See
the assistant reads a photo or a PDF you attach.
2. Data involved
| Kind | Whose | Children's? | Sensitive? | Free text? |
|---|---|---|---|---|
| The sender's email address | A non-user — whoever sent the original mail, which may or may not be another app member | Sometimes — a school or a coach may send from an address that names a child | No, not in itself | No |
| The sender's display name | The same non-user | Sometimes | No | Yes, exactly as the sender's mail client set it |
| The subject line | The same non-user | Possibly | Possibly, depending what was written | Yes |
| The message body | The same non-user | Possibly | Possibly — a forwarded email can contain anything a person put in an email: a medical appointment, a custody arrangement, a payment reminder | Yes, and unbounded until truncated |
| Attachments — names and, for allowlisted types under fixed caps, the files themselves | The same non-user | Possibly (a child's name in a filename, or in a stored file's own content) | Possibly — a PDF can carry more than the email | Yes, the filename always; the bytes for a text/calendar/application/ics/application/pdf/image/jpeg/image/png/image/webp/image/heic/text/plain file under 10 MB, up to 10 files or 25 MB per item |
| The assistant note | A member of the group — an admin, who wrote it deliberately | Possibly — it may name a child, on purpose ("emails about Ada go to Sam") | Not inherently | Yes, up to 500 characters |
| The assessment (a relevance judgement, up to 20 suggested options, a one-line summary, and the recognised part of any "Hey GroupApp" line) | Derived by a model FROM the sender's words — held on the item's own row, then copied verbatim into a household card if the model thought it worth acting on | Possibly, wherever the source email or an option's title is | Possibly, the same as the email it is drawn from | The summary and any option title/date/name are short model-written text, capped in length |
| A shared page, photo or file, and any note added before sending (added 22 September 2026) | A member of the group, sharing their OWN choice from another app | Possibly — a member might share a school notice or a photo that is about a child | Possibly, exactly like anything else a member could choose to write into the group | Yes — the shared text and any note, unbounded until truncated; a shared file follows the same allowlist and caps as an emailed attachment |
| A routine's title (built, not released, 11 October 2026) | The group — a member wrote it when they set the routine up | Possibly — a title may name a child ("Ada's lunchbox") | Not inherently | Yes, short free text the group wrote about itself |
The note differs from the four rows above it in one important way: those are a THIRD PARTY's words, forwarded into the group with no chance to consent to any of it; the note is a MEMBER's own words, written on a settings screen they chose to open, about what to expect from mail that arrives later. It carries the same fencing obligation once it reaches a model (§3, §6) because free text is free text regardless of who wrote it, but the collection question — "did the person whose words these are choose to give them to us" — is answered differently for the two.
Collected, since 21 September 2026, and previously not: the bytes of an allowlisted attachment type, under the caps §1 states. Until this change the address was never fetched at all, and this paragraph said so; this change reverses that for a closed list of types, because a filename alone did not carry what a genuinely useful attachment (a permission slip, a calendar invite) actually said, and a member could not act on it without opening the original email themselves. A type outside the allowlist, or a file over its cap, is still never fetched — only its name and the reason it was refused are kept, exactly as before this change. We also never read a mailbox — nothing is collected unless a member actively forwards a specific message.
Encrypting items (30 September 2026) adds no new kind of data. It adds an inbox keypair per key version of a group — a public key, and a private key sealed so only the group's phones and our assistant server inside a member's request can open it — and, on each item, a sealed item key and the key version it was sealed to. None of these describes anybody.
The arrival chat row (added 22 September 2026) is no new row in this table. It names an item id and when the item arrived — both already true of the pending item itself — and a fixed sentence nobody wrote. It is not a new kind of data about the sender, the household or a child; it is a second, quieter place the fact "mail arrived" is visible, alongside the Tools tile's own pending count.
Server sorting (9 October 2026) adds no new kind of data about anybody. It adds a group-level switch and its consent record, a weekly spending total per group, a count of tries on each email, and a request row (group, who asked, when, open/approved/declined — no words) when an owner or admin asks for more. The key-use record gains one word saying whether a person's request or our server's sorting asked for the key; a server row names no person.
A stated deadline on a created task (built 11 October 2026, not released) adds no new kind of data; it moves one that already exists. The date and time are already part of the assessment row above, and already reach a created event as its start. What changes is where a TASK keeps them: its own due date and time, which our server reads, instead of only the encrypted sentence recording where the task came from. Nothing new is collected — the same email, the same stated date, read the same way.
J6 (built, not released, 11 October 2026) adds the one new kind of data in this revision — the routine title row above. These are the group's own words about its own arrangements, not a third party's, and the first group-authored records other than the note to the assistant to travel on this path. Names are replaced first. Nothing else about a routine travels: not whose turn it is, not who has ticked one off, not when any of them was last done.
3. Flows and locations
| Data | Device | Supabase | Resend (Japan, Tokyo region) | Model provider | Region |
|---|---|---|---|---|---|
| The forwarded email | Never touches a device directly | Written to a table the moment it is received; the body is deleted the moment a member resolves the item, and the whole row is deleted after 30 days if nobody does | Received and parsed first; its published pricing page states 30-day data retention on the tier we use — we have not independently verified this against a signed agreement | Not sent anywhere by this step | — |
| The item, once opened | The words are shown to a member on their own screen | Read by that member's own session | — | Only when a member deliberately taps "turn it into cards" — the member's own assistant session, their own consent, their own group's region rules | Whichever region that member's assistant session uses |
| The assistant note | Typed on the settings screen; shown back to any active member who opens it | Written on the same row as the address; read by any active member | Never sent to Resend — it has nothing to do with receiving mail | Sent on a "turn into cards" turn AND on the automatic assessment turn, alongside the email that triggered it, fenced separately | Whichever region that turn uses |
| The automatic assessment turn | Never touches a device beyond the claiming member's own screen | The claiming member's app calls a claim RPC, then the assessment result is written back to the item's row and, if relevant, copied into a household card every member can read | Not involved — this reads the item already stored, not the mailbox | The email and the group's note, fenced, on the FIRST active adult member's own session to open the app after the item arrives | Whichever region that member's assistant session uses — the same rule as a manual "turn into cards" turn, because it is the identical call with a different flag |
| The record of each sorting attempt (added 1 October 2026) | Never shown to a member as a count; an owner or admin may read the rows for their own group | Written by the sorting steps themselves: the email's id, the step, a short code and the time — no words, no member | Not involved | Not involved | — |
| The Jev judgment on that turn (added 21 September 2026) | — | The two fields it decides are written with the rest of the assessment; nothing else | — | TypeSafe (Jev), United States — the redacted email, the redacted note and Gemini's options, as JSON state with Member A / Baby 1 placeholders; on every group that uses Mail Sifter since the 4 October 2026 amendment, never for an email carrying health vocabulary; the Gemini answer whenever Jev does not answer |
United States |
| An allowlisted attachment's bytes (added 21 September 2026) | Never touches a device directly; opened later through a member's own signed-URL request when they tap "View" | Fetched by the webhook from Resend AFTER the item is stored — never before — and streamed into a private bucket; deleted with the item (tombstone + hourly sweep), same 30-day outer bound as the body | Held by Resend the same way the body is, on the same published retention window, until our webhook's own fetch (a SEPARATE call from the one that fetches the body/subject) | Not sent anywhere by fetching or storing the bytes themselves — reading a calendar file's own text (below) is a separate, later step, on a member's own turn | — |
| A stored calendar file's own event text, rendered as plain lines (added 22 September 2026) | Downloaded through the member's own signed-URL request, parsed on that device into date/time fields and plain lines describing each event | Not written anywhere new — the file itself is already stored as above; nothing about this reading step is persisted separately | Not involved — this reads the file already stored, not Resend | Sent on the SAME turn as the email itself (an automatic assessment, or a member's own "turn into cards"), fenced in its own region, capped in length and count, never in a system-level instruction | Whichever region that turn uses — the same call, the same rules |
| A stored PDF attachment's own text (added 22 September 2026) | Never touches a device directly for the extraction step itself — a member's device only ever sends a reference naming the file, and only receives the extracted text back inside the same turn's reply | Our OWN SERVER downloads the file, authorised as that member (not by any elevated access of ours), and holds the extracted text only for the length of the one turn it was extracted for; nothing new is written to a table | Not involved — this reads the file already stored, not Resend | Sent on the SAME turn as the email itself, fenced in its own region, capped in length, page count and file count (a combined cap shared with the calendar row above), never in a system-level instruction; a group's own switch (admin-only, on by default) can stop this without touching anything else the item does | Whichever region that turn uses — the same call, the same rules |
| An allowlisted attachment's bytes (added 21 September 2026) | Never touches a device directly; opened later through a member's own signed-URL request when they tap "View" | Fetched by the webhook from Resend AFTER the item is stored — never before — and streamed into a private bucket; deleted with the item (tombstone + hourly sweep), same 30-day outer bound as the body | Held by Resend the same way the body is, on the same published retention window, until our webhook's own fetch (a SEPARATE call from the one that fetches the body/subject) | Not sent anywhere by this step. A PDF's text and (since 24 October 2026, see "Pictures in Mail Sifter") the words in a picture reach the assistant's model; the file itself reaches no model except a picture's pixels, re-encoded, to the picture step | — |
| A shared page, photo or file (added 22 September 2026) | Captured from another app into a small handoff area on the SAME device, then read by the sharing member's own signed-in session; any file is read and uploaded from the device directly | Written the moment the member confirms — the row and, for a file, the bucket object — under the exact same retention rule as an emailed item (30 days, or at once on resolution) | Never involved at all. A share does not touch our mail-receiving provider, is not addressed to anything, and crosses no country's border to reach us — it goes directly from the member's own device to our own server | Assessed exactly like an emailed item, once a member opens the app — the same one-time automatic pass, the same "turn into cards" | Whichever region that member's assistant session uses — identical rule to an emailed item once the item exists |
| Server sorting, in a group that turned it on (added 9 October 2026) | Never touches a device | The email, its attachments' bytes and the group's note are handed, still encrypted, to our assistant server by our own service under the database's elevated access, for one email at a time, after a key-use record is written; the result and the (encrypted) card are written back in one step | Not involved | The email and the group's note, fenced, exactly as on a member's turn; TypeSafe's second opinion as on a member's turn | Vertex global and TypeSafe (United States), as every other sorting turn since 4 October |
| A deadline the email stated, on a task a member creates (built 11 October 2026, not released; the reminder choice those columns feed is always written "off" — no card sets a reminder) | Shown on the card in the group's own zone and editable there, before any tap | Written to the task's own due date and time — plain columns, read by our server to work out when a reminder is due and whether the task is late; the email's own wording stays in the task's notes, encrypted on the phone that writes them | Not involved | Not sent anywhere by this step: the date reached a model as part of the email, on the turn the rows above describe, and this step only decides where a member's tap puts it | — |
| The group's routine titles, for a repeating arrangement (built, not released, 11 October 2026; read by the PHONE path only so far — our server's own sorting does not yet read them, so no title leaves the group on that path) | Read from the group's own records by the phone that is sorting | Read from the group's own tables by the phone that is sorting; nothing new is written, and a routine changes only when a member taps the option | Not involved | TypeSafe (Jev), United States — the titles, with names replaced, inside the same state the redacted email is already sent as; never for an email carrying health words. The titles are not sent to the generating model: which routine an email concerns is a choice, and the option's own wording is built by code | United States |
The mail leaves the group's control the moment it is sent to <token>@in.groupapp.ai — it is
addressed to a third party, and that is true of forwarding any email anywhere. Our receiving
provider is Resend, processing in Japan (Tokyo region) — not Australia, and not the
same country the rest of this platform's group data is processed in. Its published pricing page
states a 30-day retention window on the tier we use; that is what the page says, not a
contractual guarantee we have separately verified. That is stated on the switch and beside the
address, not buried.
Turning the switch off deletes the address at once, but does not touch anything already received. A pending item that arrived before the switch was turned off stays exactly as readable to every active ADULT member as it was (a child's account is refused this read by the database as of 19 September 2026) — up to its own 30-day window — until somebody resolves or it expires. Turning the feature off stops new mail; it is not an erase-what-we-hold button.
The body is written to our database in plain text. We hold no key for it and no encryption is applied to it — this is not the same protection level as a group's photographs or its assistant conversations, both of which are sealed on a member's own device before they reach us. Turning an item into cards, and the automatic assessment described in §1, are what actually reach a model — both happen only through an active adult member's own session under their own group's rules. Neither happens as part of RECEIVING the mail: the webhook that stores a pending item does nothing else, and the assessment waits for the next time somebody opens the app.
4. Legal basis and consents
The switch is consent-class: turning it on is what lets a group's mail reach Resend, in Japan — outside Australia and outside the region the rest of this platform's group data is processed in. An admin turns it on and is told, at that moment, what it means — the same sentence appears beside the address itself, so it is not a one-time disclosure a member has to remember. Turning it off removes the address at once; mail already sent to the old address before that moment is unaffected, the same as any address that stops working.
The consent lapses after twelve months, the same as every other consent-class group switch, and turning it back on asks again.
Nobody but an admin can turn this on, and nobody but an admin can see or change the address's existence — every active member can read the address once it exists, because they are the ones who might want to forward something to it.
The "let the assistant read attached PDFs" switch, added 22 September 2026, is deliberately NOT consent-class, and is not announced to the group. The test this register applies everywhere else is whether turning something on sends a household's or a child's data somewhere it would not otherwise go. Nothing new leaves as a result of this switch: the email's body already reaches the same model, on the same turns, under the same rules, and a PDF attachment is part of the SAME forwarded email — the switch only ever narrows how much of what a member already chose to forward is read, it never widens what leaves the group or where it goes. An admin can still turn it off at any time, and doing so is immediate and silent, the same as any other narrowing choice in this app that costs nobody anything by being made quietly. Sharing is NOT consent-class, and needs no switch and no admin (added 22 September 2026). The whole reason the address is consent-class is that turning it on sends a group's mail to a provider outside Australia, outside our own control, on a schedule nobody in the group chose. Sharing has none of that shape: there is no overseas processor in the path at all, and nothing happens except when the SAME member who is sharing chooses, in that moment, to send it. It is the same kind of act as posting something to the group's own chat — a member deciding, on the spot, to bring something of their own choosing into the group — and is treated the same way: open to any active adult member, needing no separate switch and no admin approval, the same as posting a message or adding a task already are.
"Sort emails as they arrive" is an opt-out group setting, not consent-class (9 October 2026; amended 10 October). The 9 October design held it consent-class, because it changes when and on whose behalf a household's mail reaches a model. We decided otherwise: the mail, the providers and the rules are those the group accepted when it turned Mail Sifter on (itself consent-class), so the switch is on by default, admin-gated by a database trigger and announced in the group chat when changed, with no consent record and no lapse. Members are told by the privacy policy's what-changed sheet. A Device-only group's mail is never handed to our server in any case: the database never does it and our server refuses the group by code.
Neither planned change of 10 October 2026 is consent-class, and one of them is close enough to be worth arguing out loud. A deadline moving from a task's encrypted notes to its own due date is plainly not: no new recipient, nothing leaving the group, and a member's own tap decides it. The routine change is the arguable one, because it sends something that was not being sent — the group's own routine titles — to a processor outside Australia. The test this register applies is whether turning something on sends a group's or a child's data somewhere it would not otherwise go, and the honest answer here is "to a recipient that is already in the path, one more short string the group wrote about itself, so that the email it is already reading can be sorted better". There is no new recipient, no new country, no new retention term and no new switch to turn on; a group that does not want any of it turns Mail Sifter off, which is the consent that covers the path. So it rides the existing consent, and the trade is recorded as an accepted residual in §8 rather than asked again — which is weaker than asking, and said so here rather than left for a reader to notice.
5. Risks and mitigations
| Risk | Who is harmed | Mitigation | Structural or conventional? | Residual |
|---|---|---|---|---|
| A member turns the switch on without reading what it means, and the group starts sending mail to Resend, in Japan, without everyone understanding that. | Every member of the group | The disclosure sentence is rendered on the switch and beside the address, worded plainly, names the destination, and is pinned by a test against overclaiming or underclaiming what happens. | Conventional — copy, test-pinned | An admin can still act for the household without asking the others first, the same as every other admin-only group switch. |
| A forwarded email contains something sensitive — a medical letter, a legal notice, a payment demand — and every active member of the group can read it, including one going through a separation the others may not know about. | Whoever the email is about, who may not be the one who forwarded it | None beyond ordinary group membership; this is the same exposure any shared calendar or task already carries once written down. | None | Accepted. The person who forwards the email is making the same choice they would make posting it to the group chat. We do not filter or moderate the content. |
| An address is guessed or leaked, and a stranger sends mail to a group that never asked for it. | The group | The address is two parts: a slug taken from the group's own name, for recognisability, and a six-character random tail, which is the part that actually has to resist a guess. A slug alone (a common family name, say) is not a secret and was never meant to be one — the tail is what makes the whole address unguessable in practice, the same protection the address had before the name was added to it. The slug is never shown to a non-member either, and rotating replaces the whole address at once. | Structural — the tail, and the RPC that only an admin may call | A determined attacker who somehow obtains a live address can send the group unwanted mail until it is rotated. That mail is still only a pending item nobody has to act on. |
| A group forwards a stream of unwanted mail (a mailing list signed up to the address by mistake, or a forwarding loop) and it piles up. | The group, and Resend's own fair-use limits | A rolling 24-hour cap per group refuses anything past it, silently, from the sender's point of view. | Structural — enforced before the row is written | A group that hits the cap loses legitimate mail for the rest of that day too; there is no separate queue for it. |
| An item nobody ever opens sits in the group's inbox holding somebody's sensitive words indefinitely. | Whoever the email is about | Deleted automatically 30 days after it arrived if nobody has acted on it; the body is deleted at once when somebody does. | Structural — a nightly sweep, shipped in the same change as this assessment | None beyond the 30 days itself, which is stated to the group. |
| A group turns the switch off believing that stops the household from being able to read what has already arrived. | Whoever the email is about | The settings screen's turning-off confirm says so before the tap takes effect: "Turning this off stops new mail arriving. Anything already sent to the old address is unaffected…" | Conventional — copy, shown as a confirm rather than after the fact | An admin who dismisses the confirm without reading it still turns it off; there is no second check. |
| A group narrows who its address accepts mail from, and a member reads that as a guarantee — but the "From" address on a piece of mail is a claim the sender's own mail server makes, and it can be forged the same as a name written on an envelope. Somebody who wants to impersonate an allowed sender can usually do so. | The group, and specifically whoever relied on the narrower setting as a lock | A sender policy — an admin chooses whether mail is accepted from any address holding the group's own address, only from an address matching an active member's own sign-in email (the default, applied to every address that already existed the moment this shipped, not only ones created afterwards), or only from an admin-curated list of addresses or whole domains. A message whose sender fails two standard, independently-checkable server-side tests outright is dropped whatever the policy says — this catches CARELESS forgery, not a determined one: those two tests are configured by the SENDING server, a sender can publish their own version of the same header we read, and nothing on our end can tell which one the server that actually delivered the mail kept. The settings screen states plainly, next to the choice, that this filters what is kept rather than authenticating who sent it, and that the address's own hard-to-guess portion is what actually keeps a stranger out (shown); since 10 October 2026 its note about the automated sender checks opens one tap away under that line, before the choice. | Conventional — a filter over already-arrived mail, backed by an automated check on the sending server's own configuration rather than by anything this app verifies. The filter is never a gate, in either direction: failing it silently drops mail with no bounce, and PASSING it is not authorisation either — a message that happens to pass those two checks is not thereby proven genuine, only not obviously forged. | Accepted, and the copy must keep saying so. A determined, technically capable sender can still get a forged message past the narrowest setting, including one that would pass the automated checks. Rotating the address remains the only mitigation that removes a sender's ability to reach the address at all. |
| A member's note to the assistant names a child, and that name reaches a model on every future "turn into cards" turn for as long as the note stands, without the member being reminded it is still there. | The child named | The note is shown back verbatim on the settings screen every time it is opened, admin-writable and member-readable, so it is never a standing fact nobody can see; it is fenced as untrusted data server-side rather than treated as an instruction. | Structural for the fence (a nonce-carrying region a forged instruction cannot escape); conventional for "the household remembers it is there" | Accepted. The note exists specifically so a name or a context CAN travel with the email — "emails about Ada go to Sam" only works if it says the name. This is the feature, not a leak of it. |
| An assessment is a MODEL'S CHARACTERISATION of a third party's email, shown to the whole group as a one-line summary and a set of suggested options — the summary could pass a verdict on the sender ("they still haven't paid") rather than stating a fact ("a payment is due Friday"), the exact risk this app already refuses elsewhere (baby care guidance, review moderation, the motivation layer's own banned-vocabulary list). | Whoever the email is about, and the group reading the summary about them | Before the summary is ever written to the item's row, agent-server scans it — and, in the same pass, any recognised forwarder instruction, every option's own title and who each option seems to be for — for a judgement about a person (characterising, blaming, urging, "should have", lateness or failure pinned on somebody, comparing people), asks the model once more naming what it found, and refuses to write anything that still fails. Since 1 October 2026 this is its own list rather than the motivation surfaces' word list, because words like "points", "late" or "fair" are ordinary facts in an email and refusing them turned valid mail into a sorting failure; every word on the motivation list is either applied here or recorded as not applying, with a reason, and a test fails when a new one is neither. | Conventional, not structural. The scan happens in agent-server, which is one caller of record_inbox_assessment — that RPC is granted to authenticated because the SAME client also needs to write a genuine assessment on the ordinary path, so nothing in the database stops a member with a valid session from calling it directly with a summary the scan never saw. The migration's own valid_inbox_assessment CHECK is a shape floor (length caps, a closed list of fields) and asserts nothing about vocabulary. |
Accepted. The scan is real and covers the ordinary path completely; a member who wanted to bypass it would have to script a direct RPC call rather than use the app, which is the same trust boundary already accepted for "Groups, not households" — an active member can already rename the group or reassign another member's tasks by the same route. |
| A member writes a "Hey GroupApp" line inside a forwarded email to steer what gets suggested — including a stranger's forwarded mail, if the group's sender policy is "anyone with the address". | The group, and whoever the suggested options would be assigned to | The instruction can only ever choose WHICH options are proposed, their titles or dates, and which members they are suggested for — the output schema's options[].kind is closed to event/task, so there is no other kind of action for an embedded instruction to reach even if a model tried to follow it, and nothing is created until a member taps a card to confirm it. |
Structural for the closed schema (there is no field an instruction could point at anything else); conventional for "the model actually stays within the three things it is told it may use the line for". | Accepted. The worst a hostile "Hey GroupApp" line can do is suggest a badly-titled task or event to a member who still has to tap to create it — the same ceiling as any other proposed option a household did not ask for. |
| The FIRST active adult member to open the app after an item arrives pays for the assessment turn out of their own weekly AI allowance and their own group's spend ledger, whether or not they are the one who cares about that particular email. | That member | None beyond the ordinary per-user weekly allowance and the platform's own spend ceilings that already bound every other assistant turn — this call is metered exactly like a manual "turn into cards" turn. | Structural for the ceiling itself; there is no mitigation for WHO is charged. | Accepted. The alternative — charging the group's admin, or splitting the cost — would need bookkeeping this app does not do anywhere else; a single household's assistant use already falls unevenly on whoever happens to open the app most, and this is the same shape of unevenness applied to one more kind of turn. |
| The assistant now states a date or time it read out of an email, which a household could mistake for something already checked or confirmed rather than a reading it can get wrong. | Whoever the group would tell about, or turn up to, a wrongly-read date | The words the email used are shown next to the assistant's own reading, so a member can compare them; nothing is written anywhere until a member taps to create it, using the app's ordinary date and time pickers, which the member can change first. A date is never invented — an email that states none leaves the field for a member to fill in themselves. | Structural for "nothing is written without a tap"; conventional for "a member actually checks the reading against the email's own words" before tapping. | Accepted. This is the same shape of trust already accepted for the assistant's summary and suggested titles on this same card (see the row above) — a member confirms before anything becomes a real record. |
| (§1, built.) A member reads "For Brendan" on a targeted card and concludes the email itself is now Brendan's private business — when every active member can still open the pending item and read the third party's words for its 30-day life. | Whoever the email is about, whose audience is wider than the card implies | The card and the item screen state the visibility plainly: recipients are who is being interrupted, and the item stays readable to the group. The wording is test-pinned the same way the switch's disclosure sentence is. | Conventional — copy, test-pinned | Accepted. The honest alternative — actually narrowing who can read the item — would turn a shared work queue into private mail between members, which this app deliberately does not have. |
| (§1, built.) Per-recipient seen state leaks sideways into a display another member can read — "Brendan has seen this" — which is the read-receipt shape this app removed for every member. | Every member; the app's own legal position | Seen state is readable by its own recipient alone, under a read rule that names them; the standing source scan that keeps feedback features out of the app's surfaces is extended over these screens before the change ships. | Structural for the read rule; the scan is test-pinned | A recipient who acts on a card is visible acting — the created task is a group record. That is the record, not a meter on the person. |
| (§1, added 22 September 2026.) An admin acts on a card addressed to Sam before Sam ever sees it — creating the task or event, or widening the audience, without Sam having been consulted. | Sam, whose card was acted on by somebody it was not addressed to | The card and the item screen name who acted (resolved_by), the same fact any other shared card already records; the created row is an ordinary group record whoever created it, and Sam can still see it, edit it, or undo it like any other task or event. Scoped to INBOX_PROPOSAL only — an admin gains nothing on any other targeted card type. |
Structural — the read/update policy is type-scoped and admin-only (is_group_admin) |
Accepted. An admin already has the authority to create the identical task or event by hand, rename the group, or reassign anybody's work; this closes a gap where a targeted card nobody on the list opened would otherwise sit until the 30-day sweep, which is a worse outcome for the household than an admin acting on it. |
| (§1, added 22 September 2026.) A child in the group chat reads "New mail arrived in Mail Sifter." — a household fact about mail this same child is refused a database read of anywhere else in this tool. | The child reading it, and the household's expectation that a child cannot tell mail has arrived at all | The sentence is fixed and names nothing: no subject, no sender, no filename, no count. The tap that opens the tool is withheld from a child's own account (isChildAccount at render), so the row's only effect for a child is the bare fact "some mail arrived", once an hour at most. |
Conventional — copy, test-pinned; the tap's withholding is a client-side courtesy, not a database refusal | Accepted. The row carries strictly less than the Tools tile's own pending count already shows an adult, and a child cannot act on it, open it, or learn anything about what it contains. |
| (Attachment bytes, built.) An attachment carries more than the email did — a PDF's own metadata, a calendar invite's organiser field, an image's own contents — and is now stored on our server, readable by every adult member, wherever the email itself would only have been described by its filename. | Whoever the attachment is actually about, who may not be the one who forwarded it | The same allowlist and caps mitigation the design's own table states: a closed list of types, 10 MB/file, 25 MB/item, 10 files/item; the same retention as the item (resolved-at-once, or 30 days); the same audience as the email itself (every active adult member, no wider). No new consent purpose — turning on Mail Sifter already covers a member's mail reaching this app's own server; this is bytes of the SAME mail the switch already discloses, not a new source. | Structural for the caps and the allowlist (a pure, unit-tested decision function, and the migration's own CHECK); conventional for "attaching a file to an email you forward is the same choice as posting it to the group chat" | Accepted, on the same basis §5's existing "a forwarded email contains something sensitive" row already accepts — an attachment is part of the same email, not a new category of harm, and the mitigation (allowlist, caps, identical retention) is what §1 states in full. |
| (Calendar options, built.) A calendar file's own event title reaches a household card verbatim, the same as a forwarder's own subject line, but without the vocabulary check this feature runs over a model's own sentences — a title a third party wrote could itself carry an unkind word about somebody, and nothing here would catch it. | Whoever the event title names or concerns | The same acceptance the assistant's own note already rests on: a third party's words, forwarded by a member, the same choice as posting the same words to the group chat; a member still has to tap the option before anything is created, and the same audience and retention rules as the rest of the card apply. | Conventional — a decision not to scan a third party's own words the same way a model's generated ones are, on the reasoning that a filename and a forwarder's subject line are already accepted unscanned for the identical reason | Accepted, on the same basis as the attachment-bytes row above — a title from the file is part of the same email a member chose to forward, not a new category of harm, and a member reviews it before tapping. |
| (PDF attachments, built, 22 September 2026.) A PDF can hold far more than a plain email ever would — a medical letter attached to a school note, a court order attached to a family arrangement email — and this is the single largest widening of what reaches a model this feature has made: text from inside a DOCUMENT, not merely a subject line or a short calendar summary, now reaches a model on the household's own opening of the app, without anyone reading the document first. | Whoever the document is actually about, who may not be the one who forwarded it and may not know it was attached | The same caps and switch this design states: twenty pages, a character cap per file and across the whole turn, at most two files a turn, extracted only under the member's own read rule, and an admin's own switch to turn the whole thing off. Nothing here is a NEW audience — the same active adult members who could already open the file and read it themselves are the only ones who ever see anything drawn from it. | Structural for the caps (enforced in code, not by a client's own restraint) and for the read rule (the extraction is authorised as the requesting member, the same as any other read of the file); conventional for "the switch stays on unless an admin thinks to turn it off," and for whether twenty pages and the character caps are the right ceiling for what this document might actually contain | Accepted, and recorded as the largest single step this feature has taken — a document's own words are read where a filename or a short summary used to be the ceiling. The switch is the mitigation an admin who disagrees can reach for; the caps bound how much of any one document is read even when nobody has. |
| (Share sheet, built.) A member shares something sensitive about somebody else — a friend's address on a party invitation, a screenshot of a message that names a third person — and every active adult member of the group they chose can now read it, the same exposure a forwarded email already carries. | Whoever the shared content is actually about, who is not the one sharing it and had no chance to agree | None beyond ordinary group membership — the same acceptance §5's very first row already makes for a forwarded email, applied to the same words arriving by a different door. | None | Accepted, on the identical basis as the very first row of this table. Sharing something into the group is the same choice as posting it to the group's chat, and this app does not filter or moderate either. |
| (Share sheet, built.) The confirm screen is the only moment a member checks what is about to be shared and with whom — a rushed tap could send the wrong file, or share with the wrong group, before reading either. | Whoever ends up seeing something that was not meant for that group, or the member who shared by mistake | The screen shows the actual text, a preview of the body, and every file by name before the one button that sends it — nothing is inferred or sent silently in the background. | Conventional — a screen, not a database rule | Accepted. The same trust already extended to every other one-tap confirm screen in this app; a mis-share is a mistake a member can see and correct by resolving or dismissing the item afterwards, not a silent or hidden one. |
| (Share sheet, built.) A shared file arrives from ANOTHER app on the same device — a photo library, a file manager, a browser's downloads — and this app never sees where it actually came from beyond what that app chose to hand over. | The member sharing, indirectly, if the source app behaved unexpectedly | The extension itself does no processing and holds no session; whatever is handed to it is exactly what the confirm screen then shows the member before anything is sent, so an unexpected file is visible and can be left out before it reaches anyone. | Structural for "the extension makes no decision and holds no session" (a property of the native code, checked directly rather than assumed); conventional for "the confirm screen shows the member enough to notice something wrong" | Accepted. This is the same trust every share-sheet integration on either operating system already asks of a user — the OS, not this app, is what decided which apps may offer this option at all. |
| (Encrypted as it arrives, built 30 September 2026.) A household reads "encrypted" and believes nobody at GroupApp or its providers can read a forwarded email. | Whoever the email is about | The statement is conditional and names the boundary in the same breath: our email provider's own copy (up to 30 days), our mail server's memory while an email arrives, and our assistant server opening it to sort it or turn it into cards. Since 10 October 2026 it opens one tap away under the always-shown sentence about our email provider. Tested for what it must not say, including that the server opens mail only inside a member's request. | Conventional — copy, test-pinned | Accepted. Email cannot be encrypted before it reaches us; what we can promise is what we keep. |
| (Encrypted as it arrives, built.) A member with a version of the app from before this change cannot read, assess or turn into cards a newly arrived email. | That member | The item shows a sentence asking them to update; the database stops an older version claiming a sealed item for assessment; our assistant server refuses a turn built from the fixed sentences. | Structural for the claim refusal; conventional for the sentence | Accepted, for the reason given in §1: the alternative keeps every group's mail readable on our servers until the last member updates. |
| (Encrypted as it arrives, built.) An owner or admin never opens the app on an up-to-date version, so the group never gets a keypair and its mail is still stored as it was sent. | Whoever the email is about | The keypair is made on the first foreground of an owner's or admin's up-to-date phone, and when Mail Sifter is turned on; a group's sealing completion is counted by the database and counts a missing keypair as not complete. | Conventional — it depends on an owner or admin updating | Accepted, and stated in the copy ("Once an owner or admin…"). |
| (6 October 2026, built.) Our server's copy of a Standard group's key cannot be written — our key service refusing, as it did for a month — so the group's mail keeps arriving as it was sent rather than encrypted. | Whoever the email is about | An owner's or admin's phone offers the copy again each time the app comes to the front, and makes the keypair as soon as it lands; the mail is removed within 30 days, as before. | Conventional — it depends on an owner or admin opening the app | Accepted. Encrypted mail the assistant cannot read could be neither sorted nor turned into cards; stored as sent, it can be, as it was before encryption. |
| (Encrypted as it arrives, built.) A group member publishes a keypair whose private half they alone could open, so everyone else sees mail as locked. | The group | Only an owner or admin may publish; the key must be sealed under the group's own key for that version (a key sealed under the phones-only key is refused); every phone checks the private half against the published public half before trusting it; the first keypair for a version cannot be replaced. | Structural for who may publish and which key it must be under; conventional for the phone's check | Accepted. An owner or admin who wanted to cause this already has plainer ways to disrupt the group. |
| (Server sorting, built 9 October 2026.) Our server sorts a Device-only group's mail. | The group, which chose that nothing reaches our servers | The database never stores mail for a Device-only group, never hands one over for sorting (the lease checks the level), checks it again when the result is saved, and our server refuses the level by code before opening anything. | Structural (database, three places) plus code | None expected. |
| (Server sorting, built.) A group forwarding a mailing list spends with nobody present. | The group, and us | A weekly amount per group (A$0.50 unless we agree more) reserved before each model call; at most two tries per email; the 50-a-day arrival cap; our platform ceilings and the kill switch. When the week's amount runs out, mail waits for a phone as before. | Structural (database) | Accepted, bounded as stated. |
| (Server sorting, built.) Our server opens a group's key with no member asking. | The group | Only for an email the database has just handed over under a single-use token; a key-use record naming our server (and no person) is written first; at most 30 such records per group per hour; Google's own key log is matched against these records nightly. | Structural for the record and the ceiling; the token is checked by the database | Accepted — the trade the switch's consent is for. |
| (Server sorting, built.) Our server and a phone both sort, and both pay. | The member and the group | A phone leaves an email our server is due to sort alone for ten minutes; either side's hold refuses the other's; only the current token can save a result. | Structural (database) | None expected. |
| (Server sorting, built.) A card raised with nobody present is a card nobody can read, or one written in plain words. | The group | A card our server raises is always addressed (the people named, else owners and admins) and the database refuses one without encrypted words; if our server cannot encrypt, it writes nothing. | Structural (a CHECK on the card) | None expected. |
| (Stated due dates, built 11 October 2026, not released; no reminder is ever set from an email — see §1 "As built".) A deadline a third party wrote in an email becomes readable metadata on our server — a task's due date and time are plain columns — where today it survives only inside the task's encrypted notes. | Whoever the email is about, whose appointment or deadline it may be | It is a date and a time, never words. It is the same readability an event created from this same card already has, and the same a task typed by hand already has. The member sees the reading on the card beside the email's own words and can change or clear it before the tap that writes it; a deadline is never filled in for an email that stated none. Our server reads it for the two things the group asked for: a reminder, and knowing a task is late. | Structural for "no tap, no row" (the card's create is fenced by the database) and for what the columns are for — a database trigger works a reminder's time out of them, which is why they are readable; conventional for "only a date the email actually stated is offered". | Accepted. A deadline is among the least revealing parts of an email and the most useful; the alternative is the task this card produces today, which nothing can remind anybody about. |
| (Stated due dates, built, not released.) A member taps through a wrongly read deadline, and a phone now rings about it — where a wrong date in a note was only a wrong note. | The member reminded, and whoever was relying on the real date | The words the email used stay beside the reading on the card and inside the task's notes, so the two can be compared; the date and time are editable before the tap and afterwards, like any other task's; the reading is anchored to the day the email itself arrived, never to whenever the sorting happens to run. | Structural for nothing being written without a tap; conventional for a member actually comparing the reading with the email's own words. | Accepted, as the same shape as the existing row above about a stated date being mistaken for something confirmed — with one more consequence attached, which is that a wrong date can now interrupt somebody. |
| (Repeating arrangements, built not released 11 October 2026.) A card option can now change a STANDING arrangement rather than add one task or event — so a careless or hostile "Hey GroupApp" line, or a misread email, can propose moving a routine the group relies on. | The group, and whoever's turn the routine would have moved | The option's kind list is UNCHANGED at two words — a routine option is a separate field no model writes, so nothing written inside an email can produce one (narrower than assessed; see §1 and §6); which routine it concerns is a choice between the group's EXISTING routines, never an identifier an email could point at; the schedule is read from the email's own words by code; the option says what it would do before it is tapped; and the change happens only on a member's tap, with the ordinary undo a routine change already has. | Structural for the option not being a kind a model can write, for the routine being one of the group's own rows, and for the field never reaching the stored record; conventional for "a member reads what the option would do before tapping". | Accepted, and recorded as a widening. The worst a bad option can now do is propose a wrong repeating arrangement instead of a wrong one-off row — a larger mistake to make, still nothing at all until somebody accepts it, and reversible afterwards. |
| (Repeating arrangements, built not released 11 October 2026; the PHONE path only — our server's sorting does not send a routine title yet.) The group's own routine titles reach a second processor overseas, and a title can name a child. | Whoever a routine title names | Names are replaced before anything is sent, by the same name map every other string on this path already goes through. Only titles travel — never whose turn it is, who ticked one off, or when. Nothing is sent at all for an email carrying health words. When the second processor does not answer, no routine option is offered rather than a worse one being guessed. | Structural for the health exclusion and for the replacement running over every string in the request; conventional for the replacement being a word match rather than a proof — a title that spells a member's name differently from the group's own records travels as written. | Accepted. It is the same recipient, under the same name replacement and the same health exclusion, as the email the titles are sent to help sort. Recorded in §8, because since 4 October 2026 that recipient is reached by every group using Mail Sifter rather than by one privacy level only. |
6. Structural versus conventional
Structural — the database enforces it:
At rest, a sealed item holds no words (added 30 September 2026). The mail server holds only the public half of the keypair and cannot open what it stores; a database function cannot open it either. The shape of a sealed assessment is still checked by the database, and an older app version cannot claim a sealed item. Only an owner or admin may publish a keypair, sealed under the group's own key for that version.
The switch cannot be flipped by a direct write, admin included. The only two writers of the column are the RPC that also mints the address and the twelve-month expiry sweep; every other write, even from an owner's own client, is refused. This closes the gap a plain admin-only trigger would leave open: an admin flipping the switch without also minting an address, which would turn the feature "on" with nowhere for mail to land.
A temporary event group and a Device-only group cannot receive mail, and cannot have the switch turned on for them, from any writer — a trigger on the item table refuses an insert regardless of who or what is writing it, not only the direct client path a policy can see.
The item's body disappears the moment it is resolved. A trigger nulls it the instant the status leaves "pending", whatever a client sends — a member cannot resolve an item and keep a copy of its text sitting in the row.
A member can read and resolve an item, and can neither create nor delete one. Only our own server, using its own elevated access, writes a new item; only a nightly sweep removes one.
A retry cannot file the same email twice. The provider's own message id is unique; a redelivered webhook call writes nothing a second time.
Only an admin may change who the address accepts mail from, and every entry on a curated list has to have the shape of an address or a domain before it is stored — a database rule and a check inside the function that writes it agree, so a malformed entry cannot land even if the screen that offers it is ever bypassed.
The note is unwritable by any client statement, not just by a non-admin one. There is no UPDATE grant on the address table at all — the admin-only RPC is the entire write surface, and the 500-character cap is additionally a CHECK constraint on the column, so a hand-crafted call that skipped the RPC's own limit would still be refused by Postgres.
The note cannot be set for a group whose inbox is off. The RPC refuses outright — the row it lives on does not exist until the switch has minted it, so there is no way for a note to exist that is not visibly attached to a live, visible address.
Only one member's device may claim an item's ONE assessment turn.
claim_inbox_assessmentsets who claimed and when only while both are still null, inside the same atomic UPDATE it checks them in — two members opening the app within the same second cannot both spend a turn on the same email. Since 1 October 2026 the claim is a short, fenced hold: nobody, the holder's own other phone included, may take a held email, and only the phone holding the current token can save a result, so an abandoned attempt can neither be retried twice in parallel nor overwrite a newer one.The record of each sorting attempt holds no words and names no member (added 1 October 2026). Its columns are the email's id, the group, the step, a short code (a single lowercase word, checked by the database) and the time; no client can write it directly, and only owners and admins can read it. It is deleted with its email and swept at 30 days.
An assessment's SHAPE is a floor Postgres enforces regardless of caller — a closed
relevanceword, a capped summary and instructions-followed length, and options whosekindcan only ever beeventortask. This is what makes the household card's own options closed by construction (§5's forwarder-instruction row) — no shape a malformed or hostile payload could take would let an option request anything the schema does not already allow. An option's newsourceword (added 22 September 2026, marking one built from a calendar file rather than a model) is closed the identical way — one of two words, or absent — so a caller cannot claim a provenance the database does not recognise either.The arrival chat row has exactly one writer, and no client may forge one (added 22 September 2026).
notify_inbox_mail_receivedis the only thing that ever inserts it — triggered by an item landing, never by a client request — and the INSERT policy on the group's chat refuses any client-writtensystem_payloadoutright, the same policy every other system row in this app already relies on. A member cannot make the row say anything else, and cannot make it appear more than once an hour.An attachment row's shape is a floor Postgres enforces regardless of caller. A
storedrow must carry anobject_path; every other status must not — thegroup_inbox_attachments_object_iff_storedCHECK — and the path itself must matchinbox/<uuid>/<uuid>/<uuid>or the insert is refused, even from the service role. No client may INSERT, UPDATE or DELETE a row at all; the webhook (service role) is the only writer.A child's account reads no attachment row, by the same restrictive policy shape already used for the item and the address.
not is_child_account(auth.uid()), ANDed with the permissive membership policy — an adult member's read is unchanged.The bucket authorises by path, plus the child refusal the photos bucket lacks.
can_access_inbox_attachment_objectchecks active standing-group membership on the group id already in the object's name, AND refuses a child's account — the photos function this bucket's own path check copies its shape from has no such check.Deletion cannot be skipped by any writer. A
BEFORE DELETEtrigger tombstones a stored object's path whenever its row is removed, whichever statement removed it — a member's resolution, an admin's item delete, the 30-day sweep, or an account erasure's cascade — because Postgres fires a row-levelBEFORE DELETEtrigger on a cascaded delete too.The switch cannot be flipped by a direct write, admin included, exactly like the note before it. There is no client UPDATE grant on the address table at all; the admin-only function that sets it is the entire write surface, and it refuses outright for a group whose inbox is off — the row the switch lives on does not exist until the switch that mints the address has run.
A PDF's text is extracted under the requesting MEMBER's own read rule, never an elevated one. The server downloads the file using that member's own authorisation, the identical check that already decides whether their own device could open the file from the item screen. A member who has left the group, or a child's account, is refused the download exactly as they would be refused the file itself.
The caps — twenty pages, a character limit per file and across the whole turn, at most two files a turn — are enforced in code that runs regardless of what any caller asks for, the same shape the calendar parser's own caps already have below.
(Share sheet.) A shared item's authority is checked in the SAME function that writes the row, not by anything upstream of it. The function that creates a shared item checks, itself, that its caller is signed in, is an active adult member of the group they named, and that the group is a standing one that has not narrowed itself to Device-only — refusing outright, and by a distinct outcome for each reason, otherwise. There is no separate gate to bypass; the write and the check are one statement.
(Share sheet.) A shared file may only be uploaded under the sharer's OWN pending share, by the sharer's own device. The rule that admits an upload names the exact item, checks it was created by THIS caller through THIS path, and refuses once the item has already been resolved — a different member, or an upload aimed at an emailed item, is refused by the same rule.
(Share sheet.) The daily cap is one number, counted under one lock, for both doors. An emailed arrival and a shared one are counted, and capped, together — a group cannot receive fifty of each by using both doors on the same day.
(Share sheet.) A child's account cannot share at all, refused by the same function that creates the row, whatever screen or shortcut a request came from.
(Sorting, 1 October 2026.) The card and the recorded result are one write, made by one database function under the phone's claim: a phone whose claim has lapsed and been taken writes neither, and a card somebody has started acting on is never replaced. An older app version still writes the two separately until it updates, so for those versions this remains as before.
Reversed 9 October 2026: "no server-side job sends an email to a model", "sorting happens only on a member's session" and "a person is charged". They remain true for every group that has turned Sort emails as they arrive off, and for the phone path in every group. What replaces them, structurally, for a group that has it on (the default since 10 October):
- Only an owner or admin can change the switch, and the group is told (a trigger, the announcement trigger). No client write by a non-admin lands, whatever screen is bypassed.
- Our server is handed an email only by one database function, only while the email is due (pending, unassessed, unheld, the switch and our platform switch on, not Device-only, not an event group, under two tries, the week not used up, a server key present), under a single-use token. Nothing a client can call hands an email to the server.
- A key-use record is written before any email is handed over, naming our server's sorting and no person, and capped per group per hour.
- The result is saved only with the current token, and re-checked when it is saved: the switch, the platform switch and the group's level are read again in the same transaction.
- A card our server raises carries encrypted words and named recipients, or is refused (a CHECK on the card row).
- A phone cannot take an email our server is due to sort for ten minutes, and neither side can take the other's held email.
(Built, not released, 11 October 2026.) A deadline reaches a task only through a member's own tap, and through the create path the database already fences. An option's row id is handed out only to the holder of the card's live claim, while the email is still unhandled, and the insert is re-checked inside its own transaction — a due date rides in on that same fence rather than getting one of its own. The columns it lands in are the ordinary ones every task uses, and a database trigger is what works a reminder's time out of them; they are readable because of that, not because this feature chose it.
(Built, not released, 11 October 2026.) An option's kind stays a CLOSED list — and it is still TWO words, not the three this was assessed as. The shape floor the database already holds over an assessment is what makes a forwarded email's embedded instruction unable to ask for anything the schema does not name. The routine option did not need a word on that list: it is a separate field, and no model writes it — our code assembles it from the second processor's two answers and its own reading of the email, so there is no wording a forwarder could put inside an email that would produce one. Stronger than assessed, not weaker, and this is the property §5's forwarder-instruction row depends on.
The field is never stored on the email's own record, and that is what the database's own shape floor enforces: the list of keys a stored assessment may carry is closed, the routine field is not on it, and one function on each sorting side removes it before anything is written. A routine option therefore exists only on the card a member was shown.
(Built, not released, 11 October 2026.) The routine itself is changed by the same call a member's own assistant already makes, under that member's own permissions. The card's tap is a member acting, so a routine belonging to another group is refused for the same reason it is refused when that member asks for it in the assistant — the read and write rules on a routine, not anything this feature adds. That is where "the right group's routine" is actually enforced.
Conventional — held by review, tests and copy, not by the database:
The scan for a judgement about a person, over a summary, an option's title and who it is for, and a recognised forwarder instruction, runs in agent-server, not in the database.
record_inbox_assessmentis granted toauthenticatedbecause that is also how a genuine assessment is written, so nothing stops a member's own client from calling it directly with text the scan never saw. See §5.Whether an address's sender check "actually" identifies the sender is not something the database, or this feature, decides. The pass/fail signal comes from a standard, independent check the SENDING mail server configures — not from anything we run or control — and the database only ever asks whether that signal says an explicit fail. Everything about how trustworthy that signal is for any given sender is outside this system, which is exactly why the filter is described to the group as a filter and not as verification.
The 30-day window is a promise the sweep keeps, not a promise the database can prove on its own — a test reads the number straight out of the migration that creates the sweep, so the two cannot silently drift apart, but nothing stops a future change from editing one and forgetting the other if that test is removed.
(Revised) We fetch only allowlisted types, under fixed caps — never "we never fetch". The webhook lists attachments and downloads only the ones a pure, unit-tested decision function decides to keep; a type outside the allowlist or a file over its cap is refused and never downloaded at all, and that discipline is a decision in the webhook's own code, called before any fetch, not a wall the database puts up — the CHECK constraint only ever sees what the code already decided to keep. A caller that bypassed the webhook entirely (there is none — service-role-only INSERT, see the structural list above) is the only thing that could write a
storedrow for a type the allowlist would have refused.The calendar parser's caps — twenty events per file, at most two files read per turn, a quarter of a megabyte read per file — and its de-duplication against a model's own suggestions are decisions in that parser's own code, not anything the database enforces. Nothing stops a future edit from reading more files, more events, or skipping the duplicate check; the shape floor the database DOES hold is on the finished option once it is about to be written (see the structural list above and the one below it), never on how the parser got there.
The webhook fetches an attachment ONLY after the item is stored, and a failed file is a ROW, never a retry. Nothing in the schema enforces the ORDER — a stored item and a stored attachment are two independent tables, and nothing stops a future edit from moving the attachment fetch earlier "for efficiency". The ordering is a decision in the webhook's own code, read at review time, the same way the body-fetch ordering already was before attachment bytes were added.
The disclosure sentence says what actually happens. Held up by a test that scans the words for the claims that would be false (that the body is encrypted, private, or unreadable by us) — a real guard, but one a determined edit could still get past if nobody reads the failure.
The note reaching a model is fenced, but that it is FREE TEXT rather than a closed choice is a decision, not a database fact. Nothing stops an admin writing something other than "what to expect from mail" into it — the field has no shape beyond a length cap. The fence protects the model from treating it as instructions; it does not, and could not, judge whether the content belongs there.
The arrival row's sentence stays content-free because a test says so, not because the database could refuse a different one (added 22 September 2026). Postgres cannot inspect whether a string is "about" an email; a test reads the migration's own literal and pins it, the same way the 30-day window above is pinned rather than proven. A future edit that parameterised the sentence with a subject or a sender would still be a valid write the database would accept.
Whether the switch stays on is entirely a household's own attention, not anything the database prompts anyone about. It defaults on, is not announced, and nothing anywhere reminds an admin it exists or asks them to reconsider it — the same posture the note already has, and for the same reason: it narrows an existing disclosure rather than granting a new one.
The page and character caps bound how much of a document is read; they say nothing about whether twenty pages was the right number for what any one document actually contains. A ceiling chosen for an ordinary permission slip or itinerary may read only a fraction of a much longer document attached by mistake, or by design — the cap is a decision in this feature's own code, not a measurement of what documents this app's members actually forward.
(Share sheet.) That the small piece of code the operating system's share sheet talks to holds no session and makes no request of its own is a property of the native code, checked directly rather than assumed. It is written once, reviewed, and confirmed against the actual configuration this app compiles — but nothing in a database can enforce what a small piece of native code does; a future change to it that quietly added either would not be caught by anything described in this document as structural.
(9 October 2026.) Our server opens only what it was handed, and refuses Device-only by code before reading — held by the assistant server's own checks and by the shape of its one reader, which takes the rows it was handed, never an id. The broker accepts only agent-server's Google-signed identity, checked in code. Both are code, not database, properties.
(9 October 2026.) The knock that starts sorting is unauthenticated, on purpose. It carries nothing and decides nothing; authority is the broker's identity check. A stranger knocking can only make sorting happen sooner.
(Built, not released, 11 October 2026.) That only a date the email actually stated is offered as a deadline is a decision in this feature's own code. The database cannot tell a date read out of an email from one a model invented; what holds it is the same discipline the card already follows for an event — the reading is shown beside the email's own words, the field is left empty when the email said nothing, and a member confirms it. Nothing stops a future edit from filling a likely-looking deadline in, and nothing in a database would notice.
(Built, not released, 11 October 2026.) That a routine title is name-replaced before it is sent, and that only titles are sent, are both code. The name map is the one every other string on this path already goes through, and it is a word match: a title that writes a member's name differently from the way the group's own records spell it goes as written. A future edit that sent whose turn it is, or when a routine was last done, would be a valid request nothing in the database could refuse.
(Built, not released, 11 October 2026.) That the schedule comes from the email's own words, never from a model's guess, is a property of the code that reads them — the same shape the calendar parser's caps already have: a decision read at review time, with nothing in the database able to tell a parsed day from an invented one.
7. Best interests of the child
Children are involved indirectly: a forwarded email can be about a child (a school notice, a medical letter) without the child being a party to any of it, and — separately — a child who is a member of the group could, in principle, forward mail to the address themselves, the same as any other member.
- What this gives a child: nothing directly. The feature is aimed at the adults running a household's paperwork.
- What it costs: a child's own name and circumstances can appear in mail a parent forwards, read by every adult in the group — no different from what already happens when a parent tells the group verbally, but now it is a written record with a 30-day life instead of a conversation with none.
- The safer design considered and only partly taken: limiting who can send to the address at all. A group can now narrow this to its own members' addresses, or to a curated list, which is an option this document originally said we had not built. What we still have not built, and do not think a mail-receiving service can honestly offer, is a way to REQUIRE the sender to be a recognised address — Resend receives on our behalf and cannot tell a genuinely forged message from a genuine one before it is opened, only whether the sending server's own configuration passed a standard check that most small senders never set up. A narrower setting lowers how much unwanted mail an ordinary group receives; it does not stop a determined, technically capable sender from reaching an address they already know.
- Where interests diverge: a parent's convenience (forward it and forget it) against a child's interest in not having their circumstances become a searchable-for-30-days record every adult in the group can open. We resolved this the same way the rest of the app resolves it for anything a parent chooses to write down about their own child: the parent's choice stands, and the 30-day window bounds how long it lasts rather than forbidding the choice.
- What a child is told: nothing specific to this feature yet — the screens that would show a child the address, or that it exists, are not built. See §8.
- A child's account cannot use the share sheet at all (added 22 September 2026). A request from a child's account is refused outright by the same rule that creates the row, and the confirm screen itself is withheld from a child's account — the same pattern already applied to the address and the settings screen above.
8. Residual risk we accept
The household-shared card is not hidden from a child's account by the database, only by the client — the pending item and the address now ARE. Until 19 September 2026,
group_inbox_items' SELECT policy andgroup_inbound_addresses' SELECT policy were bothis_active_group_member(group_id)with no age check, exactly like a household-audience action card's read rule still is today: a child's account never SAW either because the Mail Sifter tool and the Assistant tab are both absent from a child's own screens, not because a read was refused. That changed 19 September 2026. Restrictivenot is_child_account(auth.uid())policies now sit ongroup_inbox_items(SELECT and UPDATE) andgroup_inbound_addresses(SELECT), ANDed with the permissive ones — a same-group child gets zero rows from either table, at the database, whatever wrote the row asking; an adult member's read is unchanged. This is structural for every client role: a SECURITY DEFINER RPC or a service-role read is not subject to a restrictive policy, which is whyclaim_inbox_assessmentstill carries its own child refusal. The household-sharedINBOX_PROPOSALcard is deliberately NOT covered by that migration — once "Send to group" widens its audience, it is an ordinary household action card with no age check on its read rule, and a child does not see it only because a child's account has no Assistant tab to show it in. So the residual risk this bullet used to describe for the whole feature now applies to the shared card alone: a client-side gate rather than an RLS-enforced one, resting on the same tool-visibility check that hides the rest of the assistant from a child. The recipient list's own child refusal, while a card stays targeted, remainsTGT02(§1), unaffected by this migration.A child could forward mail to the group's address themselves, the same as any adult member, once the address exists. The viewing screens now hide the switch, the address and the inbox itself from a child's own account entirely (they cannot read the address there to give it to anyone, nor open the inbox to act on what arrives), but nothing stops a child who obtains the address another way — being cc'd on a family email thread, for instance — from forwarding to it themselves. We accept this now on the basis that it is no different from a child sending a message in the group chat.
A pending item's body can persist on a device longer than the server's own 30-day window. The list is part of the per-group state the app caches locally, so switching away from the group snapshots it into this device's local cache and restores it on return — a device that never reopens the group again keeps whatever it last cached, including an item's plaintext body, regardless of what the nightly sweep has since done to the server's own row. We accept this as the same shape as every other group-scoped cache in the app (tasks, chat, baby records) rather than building a special case for one table.
Showing who resolved an item is a coordination fact, not a feedback feature. The list and detail screens name which member turned an item into cards or dismissed it. This says who on the household's side acted on a THIRD PARTY's forwarded mail — the same shape as a task's assignee or an event's RSVP — never how a member responded to something another MEMBER posted, so it does not engage the "how others engaged with your material" question that the platform's wider age-classification analysis examines separately.
Whether an automatically time-limited item, visible to every member, engages the "time-limited content" question the wider platform-classification work examines elsewhere is not fully settled here. Our reading is that a forwarded email is not "posted" by an end-user in the sense that limb is about — nobody in the group publishes it for others to see as content; our system receives it from an outside sender and presents it as a work item to be actioned, the way a join request or a reminder is presented, not scrolled as a feed. But the item is genuinely visible to every active member for up to 30 days, which is the shape the question is about, and we record the honest state of the argument rather than treating it as closed. If a later, stricter reading is taken elsewhere in the platform-classification work, this retention design should be revisited alongside it.
The body is plaintext on our server, with no encryption of any kind applied to it. This is a lower bar than the rest of the app increasingly holds itself to for a group's own content, and we accept it for this first step rather than delaying the feature for a design this content does not yet have anywhere else to borrow from.
An attachment's bytes are plaintext on our server too, for the same reason and on the same basis as the body. No sealing, no key, in this design. We accept it because these bytes are the SAME email the body-plaintext decision above already accepted, allowlisted and capped rather than unbounded, and because building a Tier-1-on-the-server mechanism for content a group's own device did not write is genuinely out of scope here — see §1's own "no client write path" note for the shape a future sealed design would need (a member's device would have to hold the key, which nothing about a THIRD PARTY's forwarded file lets it do today).
We do not moderate or filter what is forwarded. A member could forward something abusive, or something that has nothing to do with the household, and every other member would see it until it is dismissed or expires. The same is true of a shared item, and here the author is never in doubt — a share names the sharer directly (§1's "second way in"), where a forwarded email's author is whoever happened to send it. That difference does not change the acceptance: a member choosing to bring their own words or their own file into the group is the same choice as posting to the group's chat, moderated the same way — which is to say, not at all.
The assistant note is group-authored free text with no shape check beyond a length cap, and it now reaches a model on the AUTOMATIC assessment turn as well as on a "turn into cards" turn — this section previously said no field reaches a model unprompted by a member, and the automatic assessment (added the same day this section was first written) makes that no longer true: the assessment turn is triggered by the app opening, not by a member choosing to send anything at that moment. We accept it for the same reason we accept the note existing at all — it is exactly what the field is for, telling the assistant what to expect from mail that arrives later, on the household's own decision to write it — and because it is never a standing INSTRUCTION: it is fenced as data on every turn it travels with, shown back to the household verbatim every time the settings screen is opened, and an admin who removes it stops it travelling on the very next assessment. What is genuinely new is the ABSENCE of a member's in-the-moment choice for this one field on this one turn; we record that plainly rather than restating the older, now-inaccurate claim.
A second overseas recipient for the email, at one level, under an open-ended retention term (added 21 September 2026). At
global_allthe redacted email and note reach TypeSafe in the United States as well as the Gemini provider. TypeSafe's policy does not state a retention window for Input. We accept it because the level is the one a group chose by two confirmations having read that everything crosses with names replaced, because the recipient does not train on Input, because the email is already a third party's words that left the group's control when it was forwarded, and because the whole call is a judgment over text Gemini was already sent on the same turn. OPEN, owner decision: whether groups already atglobal_allare told of the second provider by a one-time chat notice or re-confirmed; the copy read by groups choosing Global from now on is already amended.Email passes through our provider and our mail server as it was sent (30 September 2026). Encryption changes what we keep, not what passes through: Resend keeps its own copy for its stated retention period, and our mail server holds an email in memory while it arrives. Our assistant server can open a sealed email inside a member's request, after writing its audit record. Mail stored before a group was set up stays as it was sent until it is dealt with or reaches its 30 days, and a group with no keypair is stored as before.
A calendar file's text is still sent from the phone (30 September 2026). The phone reads a stored calendar file itself (it is sealed like every other attachment) and sends its rendered events with the assessment turn, as it did before; the email itself, the note and PDFs are read by our assistant server from the database.
(10 October 2026, owner decision.) Every group using Mail Sifter has its mail read by a model with nobody present, paid by the group, unless an owner or admin turns it off — without a fresh choice. Accepted because it is the same email, providers and rules the group accepted when it turned Mail Sifter on; members are told by the policy's what-changed sheet and the switch's own sentence. Bounded by the weekly amount, two tries per email, the platform ceilings and our kill switch; refused outright for a Device-only group.
(9 October 2026.) Our server holds a group's key for the length of one email's sorting (seconds, in memory, wiped after) rather than for one member's request. Same key, same record-first rule, a per-group ceiling instead of a per-member one.
(Built, not released, 11 October 2026.) A deadline a third party stated becomes readable metadata on our server once a member accepts it. We accept it because it is a date and a time and never words; because an event created from this same card, and every task typed by hand, are already exactly this readable; because it is what makes a reminder and an overdue task possible at all; and because nothing is written without a member's tap on a reading they can see and change. The bound is that only a deadline the email itself stated is ever offered, and that bound is code, not a database rule — §6 says so.
(Built, not released, 11 October 2026.) The group's own routine titles reach the second processor, and a card can change a standing arrangement. Two accepted steps, recorded separately because they cost different things. The titles are the first group-authored records other than the note to the assistant to leave on this path; we accept that on the same basis as the note — names replaced, a recipient that does not train on what it is sent, a judgment over text that is already being sent — and record that a name replacement is a word match. The routine option is the first thing on this card that is neither a task nor an event, and the first that changes an arrangement the group already relies on rather than adding a row; we accept it because the kind stays closed, the routine is one of the group's own, the schedule is the email's own words, and nothing happens without a member accepting it — and we record plainly that a member who taps without reading now changes more than they used to.
9. Review trigger
The two changes of 10 October 2026, both built on 11 October and neither released, are re-read before release, and again if: a deadline reaches a task without a member's tap; anything other than a date and time the email itself stated is written to a readable column; the card begins filling a deadline in for an email that stated none; a routine option is ever applied by either sorting path without a member accepting it; a routine option becomes a KIND an option may carry, or anything a model may write (it is a separate field our code builds, and the kind list is still the two words it always was — §6); a routine option is ever stored on an email's own record rather than on the card alone; the routine a change concerns is ever taken from anything but the group's own existing routines; anything about a routine other than its title is sent to a second processor; our server's own sorting begins sending routine titles (it does not today — its leased record does not carry them, so the §5 risk about titles leaving the group is a PHONE risk for now, and the day that changes is the day the server path matches what is assessed); the schedule reading widens beyond every day and named days of the week (a fortnightly or monthly arrangement needs a first date the email rarely states); a reminder is ever written from an email; a routine option is offered for an email carrying health words; or a code-only guess replaces the question Jev is asked.
J6's thresholds are measured, as of 12 October 2026. The bar the arrangement question has to clear (0.8) and the bar the choice of routine has to clear (0.7) were both written down in advance, with the rule for deciding them, and the evaluation has now been run: 144 answered calls across two arms, both bars held, and no email named the wrong routine in any of them. The firm cases separate completely from the rest, which is why 0.8 was kept rather than lowered. Re-read this section before any release that turns the option on for a real group: what was measured is our own set of emails, not a household's.
Server sorting (9 October 2026) is re-read if it is proposed for a Device-only group; the knock gains any content or authority; our server is handed anything but due emails under a token; the weekly amount is removed or made unbounded; a card it raises could be stored with plain words; sorting starts acting (creating a task or an event) rather than proposing; or any push is sent for mail without a member's own opt-in.
The inbox keypair (§1, 30 September 2026) is re-read if anything other than our assistant server's one reader or a member's phone is given a way to open an item; if the mail server is ever given anything but the public half; if a plaintext copy of an item's words is kept anywhere new (a log, a cache, a card); or if the readable parts of a sealed assessment grow beyond its relevance and each option's kind, date, time and source.
The viewing screens and the "turn into cards" step — the other half this assessment was originally written ahead of — have since been built, and this revision (2026-09-15) is that re-read, alongside the settings screen moving into the tool and the assistant note being added. This document is re-read again if the retention window changes, if Resend's own retention terms change, if the address is ever shown to or usable by a child's account, if anything starts reading an item's body other than the member resolving it, or if the assistant note gains any structure beyond free text (a picker, a vocabulary, anything that stops being "whatever the admin typed").
The targeted-audience change in §1 was assessed as a design and built the same day; the two rows in §5 are shipped facts — the card states who it is for and that the email stays visible to the group, and no member is shown another's seen state (a recipient's own badge clears on their own read of the card, which is the existing per-member mechanism and is readable only by them). This document is re-read if a later change proposes narrowing who can READ a pending item (rather than who is interrupted by it), any display of one member's seen state to another, or a notification for one of these cards.
The Jev step (§1, 21 September 2026) is re-read if: it is proposed for global_records_here
(that is a change to which node the assessment runs on, and to the ladder's own PIA); Jev is
asked to generate any text rather than judge; a question is added whose answer is written to a
field the assessment did not already carry; TypeSafe's hosting or training terms change; or the
thresholds are changed without the eval this document names — a labelled set of forwarded
emails with the member's eventual action (kept, dismissed, re-assigned) beside each Jev answer.
The open owner decision on re-confirming groups already at global_all is listed in §8 until
it is taken.
The admin card-access rule (§1, added 22 September 2026) is re-read if the admin read/update
rule ever widens beyond INBOX_PROPOSAL — to another card type, to a non-admin role, or to
anything reachable other than the Mail Sifter item screen — or if an admin's act on somebody
else's card ever stops being visible on the card and the item screen exactly as any other
resolution already is.
The arrival chat row (§1, 22 September 2026) is re-read if the sentence ever carries a
subject, a sender, a filename or a count that could be read as a verdict on the email — the
content-free promise in §6 is a test, not a database refusal, and this document's job is to
notice if that test is ever loosened rather than assume it stays true. It is also re-read if the
row ever gains a push, a badge, or a per-member seen state — each would be a small step back
toward exactly the feedback-feature and notification shapes this app has deliberately refused
elsewhere, for the group's other tools and for landing mail itself.
Attachment bytes (21 September 2026) is re-read if the allowlisted types or any of
the three caps change, if anything other than a member
viewing their own group's attachment (a signed URL, opened through the OS share sheet) ever reads
one — a model, an export, a second surface — or if the client write path added the very next day
(see immediately below) is ever widened beyond a member's own pending share.
The share sheet (22 September 2026) is re-read if: the small piece of native code the operating system talks to ever gains a session of its own or makes a network call of its own — which would move the whole trust argument this section rests on; sharing is ever made available into more than one group at a time, or into a temporary event group; a child's account is ever offered it; or the daily cap is ever split back into two separate numbers for the two doors rather than the one this document describes.
Calendar invitations become event options (22 September 2026) is re-read if anything OTHER than a calendar file's rendered event text reaches a model — a PDF's own text, an image, or anything read out of an attachment this document has not already assessed — or if the parser starts reading anything about an event beyond its own date, time, title, description or place (an organiser's own address, an attendee list, anything that names a THIRD person the household did not itself name). Also re-read if the one-sided asymmetry named in §1 — the hand path sending a file's words to a model without building the same deterministic options — is ever closed, since closing it changes what a model is asked to do with the file rather than merely what it is shown. This tenth revision is that re-read, named in the paragraph immediately above: a PDF's own text now reaches a model, which the previous revision named as exactly the condition that would require this document to be looked at again.
PDF attachments are read by the assistant (22 September 2026) is re-read if any attachment type other than a PDF or a calendar file has its content read by anything other than a member viewing it themselves (an image, a plain-text file); if the extraction ever moves onto a member's own device rather than our server, which changes the flow row in §3; if the caps (pages, characters, file count) change; if the switch defaults to off, is removed, or is ever made to gate anything other than THIS reading step; or if the extraction is ever asked to do anything beyond read text a document already contains — recognising an image inside a PDF, running OCR over a scan, or summarising rather than passing the text through unaltered.
A precondition, restated rather than assumed satisfied: the switch, the address and the disclosure sentence should not be shown to anyone before the general privacy policy names this collection — a third party's email address, subject, body and attachment names, the group's own note, the overseas recipient (Resend, Japan), and a fourth, fixed retention window (30 days) — with the policy's own version number moved so the change is a dated one and not a silent edit. This assessment does not itself verify that update has shipped; it is flagged here as an open item for whoever owns the policy document, not silently marked done because the screens exist.
The two triggers in the register apply here too: Code registration, and sign-up opening beyond the people testing it today.
10. Checklist against exposure draft s 38(2)
| s 38(2) | Requires | Answered in |
|---|---|---|
| (a) | the nature, scope, context, flow and purposes of the handling of children's personal information | §§1–3 |
| (b) | why the collection is strictly necessary | §2 — the household's own choice to forward something; nothing is collected unless a member acts |
| (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, §8 |
s 38(3): this assessment was written alongside the server-side step and before the screens that let anyone act on an item. s 39: listed on the published register.
11. Sources
Primary — law and regulator. The Children's Online Privacy Code exposure draft, ss 14(3)(b), 15–17, 38, 39 (section numbers may move on registration). The Online Safety (Age-Restricted Social Media Platforms) Rules 2025, s 4A(6), read alongside the reasoning already worked through for other group content in this register — see the cross-group event groups assessment and the on-device assistant assessment, both of which examine the same limb for different shapes of content.
Provider. Resend's own documentation for inbound email receiving, webhook signing, and message retrieval, and its published pricing page, which states a 30-day data-retention window on every plan including the free tier — read directly rather than taken from a summary.
admin-only trigger and its arm, the event-group and Device-only refusals, the retention sweep.
The migration 20260915004500_group_inbox_sender_policy.sql — the sender-policy columns, the
member and authentication checks, the admin-only RPC and its refusal codes. The migration
20260915012337_group_inbox_assistant_note.sql, which adds the note column and its RPC. The
database suites group_inbox_rls.test.ts, group_inbox_sender_policy_rls.test.ts and
group_inbox_assistant_note_rls.test.ts. The webhook function receive-inbound-email and its
two pure modules, verify.ts and decide.ts, each with their own unit suite. The extraction
fence, agent-server/src/inboundEmail.ts, and its check,
agent-server/checks/promptBoundaries.check.ts. The copy module constants/inboundEmail.ts and
its test. The settings screen, app/(tabs)/tools/inbox/settings.tsx, and the sender-policy
section mounted within it, components/Group/InboxSenderPolicySection.tsx. Our own rules: A
Household Setting Has A Named Author, Check RLS Is ENABLED Before Writing Policies, Ship
The Retention JOB Before The Retention CLAIM, Identifiers In LOGS Are Data An Erasure Cannot
Reach, Untrusted Text Gets A Fence.
The Jev step (21 September 2026). The client, agent-server/src/typesafe.ts; the questions
and thresholds, agent-server/src/inboxJudgments.ts; the seam, agent-server/src/inboxAssessment.ts;
the check, agent-server/checks/typesafe.check.ts; the price row, migration
20260921232018_typesafe_jev_price.sql; the amended copy, lib/privacyLevels.ts and
constants/legalTexts.ts (v1.11). TypeSafe's own documentation — the model card
(docs.typesafe.ai/models), the API reference and the Noul question guidance — and its
privacy policy effective 19 November 2025, read directly on 21 September 2026 for the hosting,
training and retention sentences quoted above.
The arrival chat row (22 September 2026). The migration
20260922030000_inbox_arrival_chat_notice.sql — the nullable user_id and its CHECK, the
widened system-payload vocabulary, and notify_inbox_mail_received itself. The type,
lib/systemMessages.ts's InboxMailReceivedPayload, and its test. The renderer,
components/Chat/MessageRow.tsx's system branch, and its test. The copy,
constants/inboundEmail.ts's INBOX_ARRIVAL_NOTICE / INBOX_ARRIVAL_NOTICE_QUIET_WINDOW, and
its test, which reads the migration's own literals. The database suite
__tests__/group_inbox_chat_notice.test.ts. Our own rules: A Household Setting Has A Named
Author, Engagement Stays Inside The Message: Never Counted Elsewhere, Ranked Or Pushed (no push, no badge).
Attachment bytes (21 September 2026). The migration
20260922030200_inbox_attachments.sql — the two new tables, both tombstone triggers, the
bucket, the path function and its child refusal, the storage SELECT policy, and the sweep
invoker/token functions and cron.schedule. The allowlist, caps and pure decision function,
supabase/functions/receive-inbound-email/decide.ts's decideAttachments, and its unit suite.
The post-store fetch step, the same file's index.ts. The new edge function,
supabase/functions/sweep-inbox-attachments/{index,sweep}.ts, and its unit suite. The client
types and loading, lib/inbox.ts and store/slices/createInboxSlice.ts; the viewing library,
lib/inboxAttachments.ts, following lib/photoExport.ts's own expo-file-system/expo-sharing
pattern. The item screen, app/(tabs)/tools/inbox/[itemId].tsx. The copy,
constants/inboundEmail.ts, and the legal text bullet and version bump,
constants/legalTexts.ts. Our own rules: The Avatars Bucket Authorises By Path, A Tombstone
Inside The Thing It Outlives Is Not A Tombstone, Ship The Retention JOB Before The Retention
CLAIM, The Default ACL Grants DML At CREATE TABLE, Identifiers In LOGS Are Data An Erasure
Cannot Reach.
Calendar invitations become event options (22 September 2026). The migration
20260922040000_inbox_assessment_option_source.sql — widens the option shape floor,
valid_inbox_assessment_option, with the closed source word. The parser,
lib/icsParse.ts, and its fixture suite. The merge step, lib/inboxAssessment.ts's
mergeCalendarOptions, and the reading step, lib/inboxAttachments.ts's
calendarAttachmentsOf/readInboxAttachmentText. The wiring on the automatic pass,
hooks/useInboxAssessment.ts, and on the hand path, app/(tabs)/tools/inbox/[itemId].tsx.
The server-side fence, agent-server/src/inboundEmail.ts's inboundEmailAttachmentsPreamble,
and its check, agent-server/checks/promptBoundaries.check.ts. The card's own caption,
constants/inboundEmail.ts. Our own rules: A Calendar File's Dates Are Read By A Parser, Never
By The Model, And Its Options Are Prepended, Untrusted Text Gets A Fence.
PDF attachments are read by the assistant (22 September 2026). The migration
20260922060000_inbox_read_attachments_switch.sql — the switch column and its admin-only RPC,
set_group_inbound_read_attachments. The extraction step, agent-server/src/inboundEmailAttachments.ts
— validateAttachmentRefs (the path-and-group check) and resolveInboundEmailAttachments (the
member-authorised download and the text extraction, using unpdf). The resolution wiring, before
extraction and before the assess branch, in agent-server/src/run.ts's runAgentTurn. The
raised count cap and the new cross-entry total cap in agent-server/src/inboundEmail.ts's
inboundEmailAttachmentsPreamble, and the checks pinning both,
agent-server/checks/promptBoundaries.check.ts. The client's own ref, lib/inboxAttachments.ts's
pdfAttachmentsOf, and the switch-gated field it becomes, lib/inbox.ts's inboxTurnContextFields.
The settings-screen switch, app/(tabs)/tools/inbox/settings.tsx. The copy,
constants/inboundEmail.ts. Our own rules: A Household Setting Has A Named Author, Untrusted
Text Gets A Fence, Identifiers In LOGS Are Data An Erasure Cannot Reach.
The share sheet (22 September 2026). The migration 20260922050000_inbox_share_source.sql —
the shared count-and-insert both doors now call, the sharing function itself and its refusals,
the storage insert rule scoped to a sharer's own pending share, and the function that records an
uploaded file. The database suite, __tests__/group_inbox_share_rls.test.ts (written against
this migration; run separately against the local database, not part of this register). The
native side: the third-party share-extension package this app configures, and the config-plugin
suite that pins the exact options passed to it, plugins/__tests__/withShareIntent.test.ts —
including the finding, made by actually generating the native project once into a scratch
directory, that the extension's own display name must differ from the app's own name or the
extension is silently never created at all. The pure decision function that turns whatever the
operating system handed over into a subject, a body and a decided file list,
lib/shareIntake.ts, and its unit suite. The confirm screen, app/share.tsx. The root layout's
own wiring of when that screen is reached, app/_layout.tsx. The copy,
constants/inboundEmail.ts. Our own rules: A Feature That Touches Group Data Gets A PIA First,
Ship The Retention JOB Before The Retention CLAIM, Groups, Not Households (the same-choice
argument this section's risk table leans on).
The two planned changes (10 October 2026). The card's own date resolution and its create path,
lib/inboxProposals.ts (resolveOptionWhen, buildTaskCreate, buildEventCreate) and
components/Assistant/InboxProposalCard.tsx, read to confirm what a task created from a card
carries today and what it does not. The assessment's stated-date fields, its judgement scan and
the Jev seam, agent-server/src/inboxAssessment.ts and agent-server/src/inboxJudgments.ts
(the health-word exclusion and the fallback rule read there). The sealed-field register,
lib/sealedFields.ts, for a task's notes being sealed at every level and a task's due date not
being sealed at all. The calendar parser whose caps this revision's "read by code, never guessed"
claim is modelled on, lib/icsParse.ts. Our own rules: A Calendar File's Dates Are Read By A
Parser, Never By The Model, And Its Options Are Prepended, Untrusted Text Gets A Fence, The
Options Schema Has No Kind An Embedded Instruction Could Occupy. The routines design these
changes depend on is assessed in its own entry in this register.