← All privacy impact assessments
PIA: The calendar already on your phone
Shown in the app as "Other calendars" (renamed from "Your calendar", 16 September 2026; no change to the data, the flows or anything assessed below — the tool's on-screen name only).
Status: Built, written before the code as a precondition of building it (exposure draft s 38(3)) and revised against the shipped implementation. Written 15 September 2026. Written: 15 September 2026 · Last revised: 15 September 2026
Confirmed at build time: §5.7/§6's structural claim about iOS write-only access is real, not
aspirational — the installed calendar package's default entry point takes a writeOnly boolean
on its own permission functions, distinct from its legacy entry's full-access-only ones. The
write direction was further revised after the first build to hand off to the OPERATING SYSTEM's
own add-event sheet rather than our own calendar picker — see §5.7's revision below — which is
what makes the write-only claim hold in practice, not only in the permission call.
Nothing here is legal advice. Children's Code citations are to the exposure draft;
section numbers may move on registration (due 10 Dec 2026).
1. Purpose and scope
People asked to have their group's calendar and their own calendar in one place. The obvious way to do that is to connect to Google Calendar and to iCloud, holding a permission on each member's account and synchronising in the background on our servers. We are not doing that.
Instead we use the calendar store that is already on the phone — the one the Calendar app shows, which already holds whatever iCloud, Google, Exchange and other accounts that person has signed into on that device. The operating system asks them for permission, the operating system decides what we can see, and the person can take it away in their own settings at any moment. We hold no calendar permission, no token, and no copy of anybody's calendar. Nothing about this feature runs on a server, and no table is added to our database.
Three things, in two directions:
- Writing — "Add to my calendar". A button on a group event copies it into a calendar the member picks on their own device, so it shows up beside their work meetings and their dentist.
- Reading, for conflicts. While a member is creating a group event, their own phone checks their own calendar for anything overlapping and shows a quiet note: you have something on then. The note is drawn on that phone, for that person, and goes nowhere.
- Reading, to import. A member picks events out of their own calendar and proposes them as group events. Only what they pick is written, and it arrives as an ordinary draft the group can see and change.
Out of scope, and named so that nobody assumes it was overlooked:
- A subscription feed — publishing a group's calendar as a link another calendar app can subscribe to. That is a genuinely different design: it means a URL that serves a group's events to anybody holding it, which is a capability with its own failure modes. If it is proposed, it gets its own assessment.
- Any server-side calendar synchronisation, including anything that holds a Google or Apple calendar permission on a member's behalf. Same answer: a different design, a different assessment, and the reason this one exists is precisely to avoid it.
- Reminders and tasks in the phone's own stores. Not touched, and the permission for them is not requested.
2. Data involved
| Kind | Whose | Children's? | Sensitive? | Free text? |
|---|---|---|---|---|
| A group event's title, time and place, copied out to the phone's calendar | The group's | Yes where the event is about a child — a swimming lesson, a paediatric appointment | Possibly, for the same reason | Yes, all three fields |
| The start and end times of the member's own calendar entries, read to find an overlap | The member's own, and often other people's — whoever put a meeting in their diary | Possibly | Not in themselves | No — times only |
| The title of an overlapping entry, shown to the member on their own screen | Same | Same | Possibly | Yes |
| The title, time and place of an entry the member picks to import | Same | Possibly | Possibly | Yes |
| Which calendars exist on the device, and which account each belongs to, to draw a picker | The member's own | No | No — but the account names can say where a person works | No |
Most of this is not collected by us — but one row on this list is, and it is worth being exact about which. Two of these five rows cross a boundary, and only two: a group event's fields go out to the phone's calendar when a member taps the button, and the title, time and place of an entry the member picks to import come in, written to our database as an ordinary group event — exactly as if the member had typed it themselves. Everything else — the overlap check, the titles it reads to report an overlap, the list of calendars — is read on the phone, used to draw something on that phone, and discarded; none of THAT reaches our database.
Deliberately not read, and not written:
- A calendar entry's notes are never read and never imported. The notes field of a calendar event is where dial-in codes, clinic instructions, addresses and "bring the divorce paperwork" live. Importing a title is a decision a person can make looking at the title; importing notes is a decision they would make without reading what is in them. So an import carries the title and the time, and a place only if the member leaves that on.
- Attendees, organisers and invitation status are never read. Those are other people's names and email addresses, in bulk, and we have no use for them.
- No calendar is ever read in the background, on a schedule, or while the app is not open on the screen that needs it.
- Nothing is counted. There is no record of how many entries a member has, how busy they are, or how often they used the button. A picture of how full somebody's diary is would be exactly the kind of characterisation this app refuses to build everywhere else.
Strictly necessary (s 38(2)(b)): the overlap check needs start and end times, and it needs the title only because "you have something on then" without saying what is useless. The import needs the title and the time because those are the event. The write-out needs the group event's own fields, which the member is already looking at.
3. Flows and locations
| Data | Device | Our database | Anywhere else |
|---|---|---|---|
| A group event, before the button is tapped | Already on the device, already decrypted for the screen the member is reading | Where it lives now, unchanged | — |
| The copy written into the phone's calendar | Written by the operating system into the calendar the member picked | Never returned to us. We do not store the identifier of the copy, so we cannot update or delete it later either | The account behind that calendar — Google, Apple, an employer's server — receives it the way it receives anything else that person puts in their diary |
| Entries read for an overlap | Read and used on the device, in memory, for the length of one screen | Never sent. No request body carries it, to our servers or to any model | — |
| An entry the member picks to import | Read on the device | Written as an ordinary group event, exactly as if the member had typed it | — |
| The list of calendars and their accounts | Read on the device to draw a picker | Never sent | — |
The one boundary crossing worth stating slowly. When a member taps "add to my calendar", the group's event leaves the protection this app gives it and becomes an entry in that person's own calendar account. If that account is Google's, Google now holds the title. This is true at every privacy level, and it matters most at the strictest one: a group that has chosen Device-only has done so precisely so that their event titles are encrypted on their phones and unreadable by our servers, and a single tap can put one of those titles into Google Calendar. We do not prevent it — a person's own calendar is theirs, and refusing would be us deciding for them — but the confirmation names the account the copy is going to, and at Device-only it says in plain words that the title is leaving the group's phones. §5.5 and §8 carry the residual.
The copy is a copy, and it stops being ours. Changing the group event later does not change it; deleting the group event does not delete it. We say so at the moment of the tap rather than implying a synchronisation that does not exist.
Group time survives in both directions, because both go through instants — with one deliberate exception. A group event is held as a wall-clock intention plus the group's own time zone, and it is written out to the phone's calendar as the instant that resolves to — so a member abroad sees the group's 8pm dinner at the right moment in their diary, and the group's 8pm does not move. A TIMED imported entry arrives as an instant and is turned into the group's wall-clock intention on the way in, not written as whatever the importing device's clock happened to say.
An ALL-DAY imported entry is the exception, and it is deliberate rather than an oversight: an
all-day entry is a calendar-DATE concept, not an instant. The device reports its start and end as
local midnight in whichever zone that device currently sits in, so converting that instant
through the GROUP's zone — the rule above, applied uniformly — can shift the calendar day by one
when the two zones differ: a device in Sydney's "20 September" read through an American zone can
land on the 19th. So the all-day case reads its DATE from the importing device's own zone
instead, and still writes the group's zone into the event's timezone column, same as every
other group event. Found during review, before this shipped, and fixed rather than merely
documented as a residual.
4. Legal basis and consents
No new consent purpose, and the argument is short because the test is. Every consent in this app gates something leaving the people it belongs to: a baby's day going to a model, a group's mail going to a mail provider, a member's assistant conversation going to a tracing tool. Nothing leaves here. The overlap check and the picker read data on the phone and draw something on the same phone. The write-out sends nothing to us and nothing to a third party of ours — it hands the event to the person's own calendar, which is an act they perform, on their own data, in their own account, one tap at a time. There is no standing flow to withdraw and nothing for a twelve-month re-consent to ask about. A consent purpose here would be a switch that, turned off, changed nothing we do.
The real gate is the operating system's permission, which is better than a switch of ours in three ways: the person grants it in their own words, it is enforced by the platform rather than by us, and they can revoke it in their device settings without opening this app. That is the whole consent mechanism for this feature, and the design is built to respect it rather than route around it — see §5.1 and §6.
The privacy policy gains a short section before any of this ships, saying: that the app can ask for permission to use the calendar on the device; that this is the phone's own calendar and not a connection to any calendar account; that we hold no calendar permission and no copy; that what is read is used on the device and is not sent to us; and that an event copied out to the phone's calendar goes wherever that calendar's account is, which is between the member and that account. As always, the policy's own version number moves so the change is dated, and this is a precondition rather than a follow-up.
Fair and lawful means (s 38(2)(c)): every read is in service of a screen the member has deliberately opened, every write is a tap on a named button, and the import shows exactly what will be written before it is written.
5. Risks and mitigations
| Risk | Who is harmed | Mitigation | Structural or conventional? | Residual |
|---|---|---|---|---|
| 5.1 The calendar permission is asked for at a bad moment and refused, and on iOS it can only be asked once — so the feature is dead for that person with no obvious way back. | The member | The same discipline this app already applies to notifications, for the same reason. One caller, reached only when a member taps one of these three things, never on launch and never on a screen they did not open for this. Our own sheet first, explaining what the permission is for — ours can be shown again, the system's cannot, and that asymmetry is the whole design. If they decline ours, the system dialog is never reached and the one irreversible ask survives. | Conventional, pinned by a source scan asserting there is exactly one caller — which is what the same guard does for notifications today, and which has to be widened to see the calendar call at all, because the calendar permission has a different function name. | A person who declines the system dialog has to go to their device settings. The screen says so rather than retrying. |
| 5.2 A member imports an entry from their own calendar and discloses something to the whole group that they did not mean to — a specialist's name in a title, a court date, an interview. | The member, and anybody named in the entry | Three things. The member picks each entry individually — there is no "import my calendar". A preview shows exactly the title and time that will be written, in the words the group will read. And notes are never read or carried, so the part of a calendar entry most likely to hold something private cannot be imported even by accident. | The notes exclusion is structural in the sense that the code never asks for the field — but nothing outside the code prevents a future version from asking. Call it conventional and pin it with a test. | Accepted. A member who reads the preview and taps anyway has published a title to their group, exactly as if they had typed it. That is the feature. |
| 5.3 The overlap note quotes something private, and it ends up somewhere it should not — in a request to our servers, or in a prompt to a model. | The member, and whoever the entry is about | It must never leave the device, and this is the line most likely to be crossed by a well-meant change — a "the assistant should know you are busy" improvement would do it in one line. The module that reads the calendar performs no network call and is not reachable from anything that builds a request body; the overlap result is component state on the screen that drew it. To be pinned two ways: a scan asserting the calendar module imports no client, and an assertion that no request body built by the app carries it. | Conventional, test-pinned — the same standing the on-device assistant's "sends nothing" claim has, and named as such for the same reason. | Accepted, with the tests as the alarm. §9 makes any change here a trigger. |
| 5.4 The phone is a shared family device, or is somebody else's, and "your calendar" is not the calendar of the person using the app. | Whoever owns the calendar | For the reading directions there is a genuine answer: everything we read is already visible to whoever is holding that device, because they can open the Calendar app and look. An overlap note tells them nothing they could not already see. The import direction is different — it can move somebody else's entry into a group — and there the mitigation is the preview and the per-entry choice, which is the same mitigation as §5.2 and no stronger. | None structural. The reading argument is reasoning about the device, not a control. | Accepted. A person holding somebody else's unlocked phone can already read their calendar; what this adds is a slightly easier way to republish one entry of it. |
| 5.5 A member of a Device-only group taps "add to my calendar" and the title their group encrypted on their phones lands in Google Calendar in plain text. | The group | The confirmation says plainly, before anything is asked or written, that the title is leaving the group's phones. It does NOT name a destination account — see §5.6's revision — because the OS's own add-event sheet is where the member chooses a calendar, after this confirmation, so this app never learns which one was picked. We considered refusing the button entirely at that level and decided against it: the person's calendar is theirs, and a group that chose Device-only did so to bind us, not to bind themselves. | Conventional — copy, rendered from one place and test-pinned against softening. | Accepted, and it is the sharpest edge in this design. One tap moves a title out of the only level that promises we cannot read it, to an account this app cannot even name. |
| 5.6 The calendar the member picks is an employer's, so a family event becomes visible to their workplace. | The member, and their family | Revised after the first build: this app no longer shows a picker at all. The write direction opens the operating system's own "New Event" screen — the SAME screen the OS's own Calendar app would show — and the member chooses the calendar/account there, in an interface they already know, seeing whatever labelling the OS itself gives each calendar. We cannot tell a work calendar from a personal one any more than the OS's own picker can, and there is nothing left for us to remember: the choice is made fresh, inside the OS, every time. | Conventional — the OS's own UI is the mitigation, not ours; we supply none of it. | Accepted. A member who picks their work calendar has put a family event on an employer-administered system, which that employer may be able to read. Unchanged by the revision — what changed is who draws the picker, not the risk of picking wrong. |
| 5.7 The app asks for more calendar access than it needs, so a member who only ever wanted the "add to my calendar" button has handed over the ability to read everything in their diary. | The member | Revised after the first build, and strengthened by it. On iOS 17 and later the platform offers a genuine write-only calendar permission — create entries, read nothing — and that is what the writing direction asks for. The revision closes a gap the first draft still had: even under write-only access, a picker THIS APP drew would have needed to enumerate calendars, which write-only access cannot do — so the first design was one bug away from silently requiring full access for the button to work at all. Handing off to the OS's own add-event sheet (createEventInCalendarAsync, @header systemProvidedUI) removes that requirement structurally: this app never calls a function that lists calendars for the write direction, so there is nothing here that could quietly need broader access. Full access is requested only when a member first uses the overlap check or the import, and a member who never uses those never grants it. A member who has granted write-only and later reaches for a reading feature is asked again for full access — iOS treats this as a genuine upgrade, not a re-ask of a refusal, even where the OS's own canAskAgain flag on the full-access check reads false; the app checks for a held write grant before treating that state as blocked. |
Structural on iOS, and stronger after the revision: with write-only access there is no read call in this app's OWN code path for the write direction, not merely no read the OS happens to refuse. Weaker on Android, where the two permissions sit in one permission group and granting one may carry the other; the priming sheet's own wording is platform-conditional for exactly this reason (§6). | Accepted on Android, where the separation is real in the manifest and weak in practice. Stated rather than presented as equivalent to the iOS split. |
| 5.8 Something we wrote into a member's calendar outlives the group event, or is wrong. | The member | The confirmation says the copy is a copy and will not follow changes. We do not keep the identifier of the copy, so we cannot silently reach back into somebody's calendar later either. | Structural in a small way — not storing the identifier means there is nothing to reach back with. | Accepted. A cancelled group event leaves a stale entry in a member's diary until they delete it. |
6. Structural versus conventional
The honest summary of this section is short: almost everything here is conventional, and the things that are not are enforced by the operating system rather than by us. That is unusual for this register and worth saying at the top rather than leaving a reader to work out.
Enforced by the platform, which is the strongest thing available to a feature that adds no database:
- Whether we can touch the calendar at all. The operating system asks, the person answers, and they can revoke it in their own settings whenever they like without telling us.
- Write-only access on iOS 17 and later (§5.7). A build holding write-only access cannot read a diary, whatever its code says.
- The write direction's own UI is the operating system's, not ours (§5.6/§5.7's revision). This app calls no function that lists the device's calendars for the write direction — the add event sheet and the calendar picker inside it are the OS's own — so there is no code path here that could read one even by accident.
- What is visible to us is what the platform shows us. We have no account-level permission, so there is no version of this feature that keeps working after a person revokes it.
Structural in a small way, by absence:
- The overlap check and the write-out store nothing, so there is nothing to leak, nothing to
retain, and nothing for an erasure to have to reach on those two paths. No table is added for
either. An import is different, on purpose, and is not covered by this bullet: the title,
time and place a member picks are written as an ordinary
group_schedule_eventsrow, in the existing table, and erased exactly as any other group event is — deleting the event deletes the imported one, with nothing extra needed and nothing extra built. - We do not keep the identifier of a copy we wrote, so there is no mechanism by which this app could later change or delete something in a member's own calendar.
Conventional — held by the code, by copy, and by tests, and named because a reader would otherwise assume the database was doing it:
- One caller for the permission, primed first (§5.1). A source scan is the guard, and it has to be extended to see this function at all — the existing scan looks for the notification permission's name, which is not the calendar's.
- The overlap result never leaves the device (§5.3). True because the module has no client and nothing puts it in a request body; refused by nothing else.
- Notes and attendees are never read (§2). A decision about which fields the code asks for.
- Adults only for the two reading directions (§7). A condition in the interface. Nothing in the database refuses a child's phone from reading its own calendar, and it could not — there is no server request to refuse.
- Every sentence a member reads at the moment of a tap — what is being copied, where to, that it will not follow changes, and at Device-only that the title is leaving the group's phones. Copy, from one place, pinned by a test against the claims that would be false.
7. Best interests of the child
Children are involved in two ways that pull in opposite directions, which is what makes this section worth writing rather than asserting.
Writing out is offered to everyone, children included, and that is the child-friendly half. A young person seeing "Swimming, Thursday 4pm" in the calendar app they already use is the app handing a child their own information in the place they will actually look for it. It discloses nothing new: the event is one they are already in a group with, and the copy goes into their own device's calendar. Withholding it would be paternalism with no privacy gain.
Reading is not offered to children in this version, and the two reading directions deserve different answers.
- Import is the one we are confident about. A child's own calendar is theirs — a school timetable, a counselling appointment, a friend's party, a parent they see on alternate weekends. An import button on a child's phone is a smooth path from my private diary to something every adult in my group can read, taken by somebody who may not weigh that the way an adult would. The Code's concern is exactly this: a design that makes disclosure the easy action. So it is not offered.
- Conflict awareness, honestly, has a much weaker case against it. It discloses nothing to anybody: it reads a child's calendar and shows that child a note on their own screen. On its own merits a child could have it. The reason it is withheld anyway is the permission, not the feature: on iOS the overlap check needs full calendar access, the same grant the import needs, and asking a child to hand over read access to their entire diary in order to be told "you have something on then" is a worse trade than not offering it. If the two are ever separated — a platform change, or a design that does not need the read — this decision should be revisited rather than inherited.
Where the interests of child and parent diverge: a parent would find it useful to have a child's activities imported into the group calendar. The child has an interest in their own diary not becoming a group document. The child's interest wins here, and a parent who wants a child's commitment on the group calendar types it in, which they can already do.
What a child is told: the writing button says where the copy is going, the same as for anybody. Nothing about this feature changes what the app's existing page for children says about what the adults around them can see, because nothing about this feature shows an adult anything new about a child.
This is not an argument about the under-16 rule. Holding a feature back from children carries no weight in that question, as our own standing correction says, and it is not cited here as if it did.
8. Residual risk we accept
- One tap can move a Device-only group's event title into Google Calendar (§5.5). We have chosen disclosure over refusal, and the disclosure is a sentence somebody in a hurry can skip. This is the most surprising thing in the design and it is accepted deliberately, not overlooked.
- "The overlap note never leaves the device" is held by tests, not by the runtime. A future change that makes the assistant aware a member is busy would breach it in one line, in a file two steps away, and would look like an improvement while doing so.
- The Android permission separation is weaker than the iOS one (§5.7). On iOS a member who only wants the button genuinely cannot be read; on Android the two permissions sit in one group and that guarantee is not available.
- Anything a member imports, they have published to their group, and the preview is the whole protection. Somebody's calendar can contain a diagnosis in its title.
- We cannot tell an employer's calendar from a personal one (§5.6), and a member who picks the wrong one has put family information on a system their employer administers.
- A copy we write is not ours and is not tracked, so a cancelled or corrected group event leaves a wrong entry in somebody's diary. We say so; we do not fix it.
- "Adults only" for reading is a condition in the interface and nothing else. There is no server request for a server to refuse, so there is no stronger version of it available in this design.
- A member who taps "add to my calendar" twice gets two entries, not a warning. The design does not remember the identifier of what it wrote (§5.8's own reasoning — deliberately, so this app can never reach back into a member's calendar later), so it has no way to notice a repeat and no way to offer to skip it. The OS's own add-event sheet reopens fresh each time, pre-filled the same way. Accepted as the cost of not tracking what we wrote, which is the stronger property.
- The overlap check misses an entry longer than 14 days on either side of the window being
checked. The Android calendar provider queries for CONTAINMENT within a window, not overlap,
so
findOverlapswidens the window it asks for and relies on its own filter to decide overlap correctly — but the widened window is still a fixed size (14 days each side), chosen to cover a week of leave and a genuinely long absence, not an unbounded one. A month-or-more-long entry starting more than 14 days before a checked window is reported as no conflict when one exists. The alternative — an unbounded query — would read a member's whole calendar into memory to answer a one-hour conflict check, which is a worse trade. Accepted, and the fourteen-day bound is a named constant in the code rather than a number left implicit somewhere in a query.
9. Review trigger
Re-read this document when any of these stops being true:
- Anything read from a device calendar is put into a request body — to our servers, to a model, to anything (§5.3). This is the one that would change what the feature is.
- A calendar entry's notes, attendees or organiser are read for any purpose.
- A calendar is read in the background, on a schedule, or anywhere other than the screen the member opened for it.
- The feature stops being device-only in any respect — a subscription feed, a server-side synchronisation, or any permission held on a member's calendar account. Each of those is a new assessment, not a revision of this one.
- A reading direction is offered to child accounts, or the permission split that §7 turns on changes on either platform.
- The write-out starts remembering the identifier of what it wrote, which would make this app able to reach into a member's own calendar later.
- Anything about a member's calendar starts being counted, stored or summarised.
Triggered 25 September 2026, and answered by a separate assessment: keeping the two calendars in sync remembers what it wrote, reads whenever the app is open on the group, and brings entries in by calendar rather than by entry — four of the triggers above at once. That design has its own assessment on this register, "Keeping the group's calendar and your phone's calendar in step". Everything this document says about the single-event copy, the overlap note and the hand import is unchanged by it.
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 — and the honest answer for most of it is that nothing is collected by us at all |
| (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, §6 |
| (f) | risk of harm to, and impact on, children | §5, §7, §8 |
s 38(3): written before the code. s 39: listed on our published register.
11. Sources
Primary — law. Privacy Act 1988 (Cth), Australian Privacy Principles 1 (which is why §4 makes the policy amendment a precondition), 3 and 5 (collection and notification), 6 (use and disclosure) and 8 (cross-border disclosure — not engaged by this design, because nothing about a member's calendar reaches us or any recipient of ours; where a member's own calendar account is overseas, that is their existing relationship with that provider and not a disclosure by us). The Children's Online Privacy Code exposure draft, ss 10, 13, 20, 23, 33, 38, 39; section numbers may move on registration.
Primary — platform documentation. Expo's documentation for the calendar module in the SDK version this app is on: the permission functions, the iOS usage-description keys including the write-only key introduced for iOS 17, the Android calendar permissions, and the functions for listing calendars, creating an event and querying a date range. Apple's platform documentation for calendar access, including the write-only authorisation introduced in iOS 17 and the requirement that an app declare a purpose string. Android's documentation for the calendar permissions and for permission groups, which is the source for §5.7's statement that the separation is weaker there.
In-repo. lib/notificationPermission.ts and lib/__tests__/notificationPermission.test.ts —
the one-caller, primed-first pattern §5.1 copies, and the source scan that enforces it, which does
not currently see a calendar permission call and has to be widened. lib/time.ts and the dual
storage of a group event's wall-clock intention and time zone — the reason §3 can say group time
survives in both directions. lib/scheduleConflicts.ts — the existing, entirely in-app conflict
scan that the device-calendar overlap note sits beside without joining. Our own written rules:
Group Time Has Exactly One Exception, And It Has To Pass A Test, A Task Reminder Is DISPATCHED,
Never Scheduled On A Device (for the permission discipline it records), Locked Fails Closed,
Privacy Copy Is Tested For What It Must NOT Say, Feature Release & Migration Strategy (a new
native module cannot reach people over the air, which is why this ships in an app update).