Skip to main content

Children's privacy (COPPA)

Status: ⚠️ Compliance — engineering substrate BUILT; legal VPC-method-sufficiency review DEFERRED (product ships for solo self-testing; hard legal gate before public launch)

Scope

COPPA requires verifiable parental consent before collecting personal information from children under 13. Rewhaven must age-gate account creation, obtain and record explicit parental consent, minimize data collected for minors, and provide a deletion path. This is the highest-priority compliance item given the product's audience. No behavioral advertising targeting minors under any circumstances.

Shipped mechanism (COPPA Layer 1 + 2)

Both the parent-creates-child-member path and the child self-signup + consent gate have shipped. The engineering substrate covers:

Schema + RLS

  • MemberStatus.pendingConsent — a child who has linked their own login but whose household has not yet completed VPC sits in household_members with status='pendingConsent', kind='child', consent_state='none'. RLS is frozen for unconsented children: they cannot read or write household data until a parent approves.
  • SECURITY DEFINER child-link RPC — the child-signup flow calls a server-side RPC to link the child's auth user into the household member row without exposing parent data to the unauthenticated child session.
  • Parent code-issuance UI (L1-T12): a parent generates a short-lived link/code that the child uses to join the household.
  • Household approval surface (VPC → captureConsent): a parent reviews and explicitly approves the pending child membership.
  • decline_child RPC: parent rejects, hard-deletes the child member row and its auth user.
  • Child-signup + waiting app screens: the child sees an in-app waiting state until the parent approves or declines.

Expiry + orphan cleanup

  • expire-pending-children Edge Function (infra/supabase/functions/expire-pending-children/index.ts, commit a0c35f8) — scheduled reaper. Deletes pendingConsent child members whose VPC window has expired (7 days, per COPPA delete-if-no-consent requirement). Also sweeps orphaned child auth users whose member row was already removed (step-2 failure rollback gap). Invoked by scheduler only; guarded by shared secret (x-cron-secret). Deployed with verify_jwt OFF.
  • Expiry index: infra/supabase/migrations/20260713000100_pending_child_expiry_index.sql

Migrations

FileWhat it does
20260712000100_member_status_pending_consent.sqlWidens household_members_status_check to admit 'pendingConsent'
20260712000200_link_child_rpc.sqlSECURITY DEFINER RPC that links a child auth user to an existing shadow member row
20260712000300_child_consent_rls_freeze.sqlRLS policies that block unconsented children from reading/writing household data
20260712000400_decline_child_rpc.sqlParent-side decline RPC — hard-deletes the pending child member and auth user
20260712000500_child_link_hardening.sqlAdditional authz hardening for the link flow
20260713000100_pending_child_expiry_index.sqlIndex on (status, created_at) for the scheduled expiry sweep

Residual open item

The legal VPC-method-sufficiency review is still deferred. The current mechanism (parent code-issuance + in-app approval) is the product-engineering implementation. Whether it satisfies the COPPA "verifiable" bar (as distinct from the FTC's enumerated methods such as credit-card micro-charge or signed consent form) requires legal sign-off before public go-live. Product ships for solo self-testing under this deferred gate.

Relationship

Personas — child members are the highest-risk group; consent must be parent-granted.