KindCircl Data Retention Policy

Owner: Ali Salomi · Effective: October 20, 2026 · Review: at least once a year
Systems: Firebase project circl-pilot, Firestore database in us-west2 (Los Angeles); Cloud Storage bucket circl-pilot.firebasestorage.app in US-WEST1 (Oregon), used only for signed consent forms.

Principles

  1. Keep children's personal information only as long as reasonably necessary for the specific purpose it was collected for, and not indefinitely.
  2. Delete it using reasonable measures to prevent unauthorized access during deletion (Firestore document deletion, after which Google purges it under its deletion process).
  3. When a parent deletes a child's account, delete the child's personal information promptly, except for the safety records listed below.

Retention schedule

Data (location) Purpose Business need Retention Mechanism (as built)
Chat messages and stickers (circls/*/messages, dms/*/messages) Deliver chat; parent review of DMs Recent conversation history 90 days from sending Firestore TTL on expireAt
Messages stopped by the filter None None Not stored sendMessage returns before writing
Safety reports (reports), incl. up to 300-character excerpt and kid-typed details Safety review; legal reporting Detect repeat abuse; NCMEC duties About 1 year from creation Firestore TTL on expireAt (1 year); daily cleanup also deletes reviewed reports older than 1 year. Reports a kid filed are deleted with that kid's account; reports about a kid are kept until they expire.
Parent activity feed (parents/*/activity) Alerts and approvals for parents Recent safety history 1 year Firestore TTL on expireAt
Admin audit log (auditLog) Accountability for safety-team actions Review of moderation decisions 2 years Firestore TTL on expireAt; daily cleanup backstop
Consent sessions (consentSessions): parent uid, Stripe Checkout session id, payment intent id, refund id and status, amount (50 cents). Never card details. Match Stripe results to parents; confirm the refund Short-term 30 days Firestore TTL on expireAt
Card check summary on the parent record (parents/{uid}.consentCard): session id, amount, refund status Proof of consent (COPPA 312.5(b)(2)(ii)) Demonstrate that verifiable consent was obtained While the parent account exists deleteParentAccount
Processed Stripe webhook event ids (stripeEvents) Process each Stripe event once Short-term 90 days Firestore TTL on expireAt
Signed consent form files (Cloud Storage consentForms/{parentUid}/...): photo or PDF showing parent name, signature, date, account email, child usernames Verify consent (COPPA 312.5(b)(2)(i)); proof of consent Demonstrate that verifiable consent was obtained Approved: while the parent account exists. Sent back: deleted immediately. decideConsent deletes rejected files; deleteParentAccount and the 30-day unverified cleanup delete consentForms/{uid}/; submitConsentForm deletes an earlier waiting file when a new one is sent
Consent review record (consentReviews/{parentUid}): email, typed signer name, child usernames, file path, submission time, decision, reviewer, note Admin review workflow Track decisions 1 year from submission, or sooner with the parent account Firestore TTL on expireAt; deleteParentAccount
Pairing codes (pairingCodes) Sign a kid's device in 10 minutes Deleted on use; expired codes removed by daily cleanup redeemPairingCode; dailyCleanup (3:15 a.m. Pacific)
Pairing rate-limit records: HMAC-SHA256 of IP with a secret salt, plus counter Stop code guessing Short-term abuse prevention Up to 1 day (removed by the next daily cleanup) dailyCleanup deletes records older than 1 day. The raw IP is never stored.
Per-kid message rate-limit records (rateLimits) Abuse prevention Minutes Up to 1 day; deleted with the kid's account dailyCleanup; deleteKid
Kid profile: username, age group, avatar and avatar look, friend code, CirBux, ledger, owned items, card collection with Buddy levels and XP (kids/*/cards), the chosen Buddy, free packs and the Founding Member number, settings, kindness counts (kids/*, profiles/*, usernames/*, friendCodes/*) Run the account While the account is in use Until the parent deletes the kid or their own account deleteKid, deleteParentAccount
Squads (squads/*, squadInvites/*): name, emoji, color, members, parents, read markers Run Squads While the Squad exists When the owner closes it or their account is deleted (the Squad and its chat are deleted). A member who leaves or is deleted is removed at once. leaveSquad, deleteKid
Live game rooms (rooms/*, rooms/*/hands/*, roomSecrets/*, roomCodes/*, roomInvites/*): players' usernames, looks and Buddies, answers, picks, card hands, letters and wagers, scores, reactions Run live games 30 minutes after the last activity Firestore TTL and the daily cleanup delete idle rooms; empty rooms are deleted at once; a deleted kid is removed from rooms at once TTL policy in firestore.indexes.json (also on the hands collection group), cleanup, leaveRoom, deleteKid
Game Hub best scores (kids/{uid}.best): the kid's highest solo score for each game Show "Your best" in the Game Hub While the account exists Deleted with the kid's account deleteKid
Teams (teams/*): team name, type, organizer display name, organizer parent id, age groups, member kid ids and usernames, member parent ids and the first letter of each parent's email, captains, milestones paid Run Team Circls While the team exists When the organizer ends it or deletes their account; a member is removed at once when removed, taken out by their parent, deleted, or paused by withdrawn consent endTeam, removeFromTeam, deleteKid, revokeConsent, deleteParentAccount
Team chat and announcements (teams/*/messages) Deliver team chat 90 days Firestore TTL; deleted with the team; a deleted kid's messages are removed at once TTL policy, endTeam, deleteKid
Team codes (teamCodes/*, teams/*/org/info) Let parents join While the code is current Deleted when the organizer makes a new code or ends the team regenerateTeamCode, endTeam
Team weekly challenges and trophies (teams/*/challenges/*, teams/*/trophies/*) Weekly team challenge While the team exists Deleted with the team; a removed kid's id is removed at once endTeam, removeFromTeam
Squad daily activity (squads/*/stats/*): games played per day, who played, and which members chatted that day (ids only, no message text) Squad streaks and Squad activity While the Squad exists Deleted with the Squad leaveSquad, deleteKid
Squad streak (squads/{id}.streak): day count, best, last counted day, monthly freeze, flame flair Squad streaks While the Squad exists Deleted with the Squad leaveSquad
Weekly challenges and trophies (squads/*/challenges/*, squads/*/trophies/*): which challenge, how much each member helped, who got the reward Weekly Squad Challenge and trophy shelf While the Squad exists Deleted with the Squad; a deleted kid's id is removed from them at once leaveSquad, deleteKid
Squad chat (squads/*/messages) Deliver chat 90 days Firestore TTL deletes after 90 days; a deleted kid's messages are removed at once TTL policy, deleteKid
Invite records (inviteRewards/*, inviteCaps/*, parents/*.pendingInvite) Give the free packs once per pair and enforce the monthly cap While the accounts exist With the parent or kid account deleteParentAccount
Friendships, friend requests, join requests, memberships Run friendships and clubs While the account is in use Account deletion deleteKid
Circls the kid created Run the club Other members rely on it Deleted if the kid is the only member; otherwise kept with no owner deleteKid
DM threads with a deleted kid Let the other kid keep their own messages The other kid's content Deleted kid's messages removed immediately; thread marked closed; the rest expire at 90 days deleteKid
Blocks made by the kid, and other kids' block entries about the kid Safety While the account is in use Account deletion deleteKid
Kid login record (Firebase Auth: UID, display name = username, creation and last sign-in time) Authentication While the account is in use Account deletion auth.deleteUser in deleteKid
Parent record, email, login and consent record Parent account; proof of consent While the parent uses KindCircl Until the parent deletes their account deleteParentAccount (deletes all kids, parent record, activity, consent sessions and login)
Unverified parent accounts with no kids Request consent Only while consent is pending 30 days (parents with a form waiting for review are skipped) dailyCleanup (also deletes their consent form files and review record)
Google Cloud Logging Security and troubleshooting Detect abuse _Default bucket about 30 days; _Required admin audit logs about 400 days (set by Google) Cloud Logging retention

Withdrawn consent

revokeConsent sets the parent's status to revoked, clears the consented claim, and pauses every kid account immediately, so no further information is collected. Data remains until the parent deletes the accounts or re-verifies (which unpauses them). Attorney to confirm whether revoked accounts should also be auto-deleted after a set period.

Remaining gaps

  1. Inactivity deletion (24 months) is not built yet. Build it with a parent email warning 30 days before deletion.
  2. Legal holds: there is no automatic hold flag. If a report is sent to NCMEC or law enforcement requests preservation, the coordinator must export the records to restricted storage before the 1-year TTL deletes them, and keep them for the required period (1 year after a CyberTipline report under the REPORT Act).

Annual review

The Ali Salomi reviews this schedule at least once a year and whenever a feature adds new data, and updates Privacy Policy section 8 to match.