Terms & consent — requirements
Epic — release gate. MVP-1 requirements for the consent-record substrate (see the feature architecture). These are pass/fail launch conditions, audited each release and continuously in production. Not legal advice — counsel must sign off on VPC method and re-consent triggers. The Children's privacy (COPPA) epic depends on these records.
| Type | Non-functional |
| Layer (build approach) | Cross — consent record + re-consent gate (SDK service + RLS + UI) |
| RICE | R 10 × I 2 × C 80% / E 2 = 8.0 · Tier MVP-1 |
| KPI (summary) | Consent-acceptance % (100% pre-use); re-consent completion — see Success criteria |
| Traces to | feature terms-consent · C4 auth |
| Depends on | Children's privacy (COPPA) (VPC definition + method) · Account (account holder is the consenting adult) |
Success criteria (definitive KPI)
Success = these gates hold at 100%, verified each release and sampled continuously in production:
- ToS acceptance gate: 100% of active sessions are preceded by a recorded acceptance of the current Terms of Service and Privacy Policy — zero sessions reach app functionality without a current acceptance record.
- VPC gate: 100% of under-13 child members have a current verifiable-parental-consent
record before any child-data write — zero child records written without a
consentRef. - Re-consent completion: when a material version bump occurs, re-consent completion ≥ 85% of affected accounts within 14 days of the version going live; accounts that do not re-consent are suspended from child-data writes (and from the app, for the adult gate) until they do.
Window: continuous; every release must re-prove both gates before ship. A single violation of either gate fails the release condition — no ramp.
Measurement & audit
Instrument the consent substrate so every gate is provable. No child PII in any payload; child and parent references are opaque/hashed:
| Event | When | Key properties |
|---|---|---|
terms_accepted | account holder accepts ToS + Privacy Policy | version, timestamp — no user PII in BI tier |
consent_captured | parent completes VPC for a child | parentRef, method, consentVersion, timestamp, consentRef |
reconsent_completed | account completes re-consent after version bump | version, days_since_bump, accountType (adult|parent) |
| (audit) | release + nightly | assert 0 active sessions without a current ToS record; assert 0 child records lacking a consentRef |
Privacy model for these events:
- OPERATIONAL (child PII → VPC):
consent_capturedrecords method, parentRef, consentRef — retained for the life of the consent relationship. - INTERNAL BI:
terms_acceptedandreconsent_completedcarry version + coarse timing only; no child identity; content-free; never marketing. - MARKETING: parent/account count and plan type only; never child-derived; never targets children.
Scope
This epic owns the consent-record substrate that the rest of the system builds on:
- Adult ToS + Privacy Policy acceptance — recorded on first use before any app functionality is accessible; version-stamped; blocks the session if absent.
- Verifiable parental consent (VPC) records for child members — method, consenting-parent reference, child reference, consent version, timestamp; the record is a hard prerequisite for any child-data write.
- Consent versioning — each ToS/Privacy-Policy version and VPC version is tracked; a new version triggers a re-consent gate on next launch.
- Re-consent on material change — accounts are blocked from the app (adult gate) or from child-data writes (VPC gate) until re-consent is recorded for the current version.
Out of scope here: COPPA-specific data-minimization, no-marketing, and parental-deletion controls — those are governed by Children's privacy (COPPA).
Non-functional requirements
NFR-CONSENT-1 — Adult ToS + Privacy Policy acceptance pre-use gate
Priority: P1 · Status: 🔨 to build
Statement. No account holder accesses app functionality until they have accepted the current Terms of Service and Privacy Policy; the acceptance is recorded with version and timestamp before any session proceeds.
Acceptance
- Given a new account holder When they launch the app Then an
acceptance gate is presented before any functional screen; no data is read or
written until acceptance is recorded (
terms_acceptedfires). - Given an existing account with a current acceptance When they launch Then the gate does not re-appear.
- Given the gate displayed When the user declines Then the session terminates and no data is written.
NFR-CONSENT-2 — VPC record required before any child-data write
Priority: P1 · Status: 🔨 to build
Statement. The SDK service refuses to persist any child PII — name, emoji, age band, wallet, goals, chore completions — until a verifiable-parental-consent record (method, parentRef, consentVersion, timestamp) exists for that child, tied to the creating parent. Enforcement lives in the service (offline-safe) and in Supabase RLS (cloud-side); it cannot be bypassed by a direct write.
Acceptance
- Given a parent creating a child member When VPC has not been captured
Then the service returns an error and no child record is written
(
child_member_createdrequires aconsentRef). - Given VPC captured Then
consent_capturedfires and theconsentRefis present on the child record before the child write proceeds. - Given a direct Supabase write without a valid
consentRefThen the RLS policy rejects the write, independent of SDK enforcement.
NFR-CONSENT-3 — Consent versioning + version gating
Priority: P1 · Status: 🔨 to build
Statement. Both ToS/Privacy-Policy versions and VPC consent versions are tracked as first-class values. The service compares the stored acceptance version against the current version at session start; a stale version triggers a re-consent gate before any data operation proceeds.
Acceptance
- Given the current ToS version bumped When a returning account holder launches Then the re-consent gate fires before any functional screen is accessible.
- Given the current VPC version bumped When a parent opens the app Then re-consent is required for each child before further child-data writes proceed.
NFR-CONSENT-4 — Re-consent completion within SLA
Priority: P1 · Status: 🔨 to build
Statement. On a material version bump, affected accounts must complete
re-consent within 14 days; accounts that do not re-consent are suspended from
child-data writes (and from the app, for the adult gate) until they do. A
reconsent_completed event is emitted on completion.
Acceptance
- Given a version bump deployed When an account has not re-consented within 14 days Then child-data writes are blocked and a re-consent prompt is shown on next launch.
- Given re-consent completed When
reconsent_completedfires Then the gate lifts and child-data writes resume immediately.
NFR-CONSENT-5 — Consent record integrity + auditability
Priority: P1 · Status: 🔨 to build
Statement. Consent records are append-only and immutable after creation; each record carries method, version, timestamp, and opaque parent/child references. Records are retained for the life of the consent relationship and are auditable without exposing child PII.
Acceptance
- Given a stored consent record When any system process reads it Then method, version, and timestamp are present and unmodified.
- Given the nightly audit When it runs Then zero child records lack a
consentRefand zero active sessions lack a current ToS acceptance.
NFR-CONSENT-6 — Offline behaviour: cache acceptance; hold child-data gate
Priority: P1 · Status: 🔨 to build
Statement. ToS acceptance and VPC consent records are cached locally so the app functions offline for accounts with a current acceptance. The child-data write gate is enforced locally via the cached VPC record; without a cached record for a child, child-data writes are held until connectivity is restored and the record is confirmed from the cloud.
Acceptance
- Given an account with a current ToS acceptance When the device is offline Then the app proceeds normally without re-presenting the acceptance gate.
- Given a child with no cached VPC record When the device is offline Then child-data writes are blocked until the record is fetched on reconnect.
Architecture considerations
- Consent record as a first-class entity. The substrate defines two record types: (1) an account-level ToS acceptance (version, timestamp, accountRef) and (2) a child-level VPC record (method, parentRef, childRef, consentVersion, timestamp, consentRef). These are separate entities; the VPC record joins to the child member, and deletion of the VPC record cascades to child PII (cascade owned by the COPPA epic, gated on this record existing).
- Version gating in the service layer. At session start the service compares the current published version against the stored acceptance version; a mismatch surfaces a re-consent event to the presentation layer and blocks all data operations until the record is updated.
- Service-layer gate (offline-safe). The SDK service enforces the VPC check locally using the Drift-cached record. No child-data write proceeds without a local VPC record for that child. This gate cannot be short-circuited through the repository or presentation layers — the enforcement lives in the Service, not the UI.
- RLS as the cloud-side backstop. Supabase RLS policies mirror the service
gate: a child row without a valid
consentRefis rejected at the database boundary, independent of SDK enforcement. Defence-in-depth, not the primary gate. - Offline behaviour. Accepted consent records are written to the local Drift store at acceptance time. The app reads from this cache when offline. The child-data gate holds if the child's VPC record is absent from cache — the service does not optimistically assume consent.
- Shadow member activation. A
shadowhousehold member must complete ToS acceptance before being activated as a full account — see Open decisions.
Design work (ahead of build)
- Adult acceptance gate — the full-screen ToS + Privacy Policy presentation on first launch and on version bump; must meet the a11y floor (Atkinson body, readable contrast, scroll-to-bottom confirmation before the accept button activates); must not be dismissible without accepting or declining.
- VPC capture flow — the parent-facing screen that collects verifiable parental consent before the child member is created; method TBD (see Open decisions); must clearly name the child, state what data will be collected, and confirm which parent is consenting.
- Re-consent prompt — the version-bump screen shown at next launch; must distinguish between a ToS bump (adult gate) and a VPC bump (parent gate per child); must not be dismissible without acting.
- Consent status surface — a lightweight entry in account settings where the adult can review their current accepted version and, for parents, the VPC status of each child.
Decisions (resolved for MVP-1)
Resolved — see the MVP-1 decisions log for the canonical record, rationale, and status legend (✅ decided · ⚖️ counsel confirms · 🔜 MVP-1.x).
- D-CONSENT-1 — VPC method. ⚖️ Same as D-COPPA-1 — email-plus (free) + card (paid); counsel confirms. NFR-CONSENT-2 specced on that.
- D-CONSENT-2 — "Material change" definition. ⚖️ A material change = any change to data collected, purposes, processors/sub-processors, or sharing; copy/clarity edits are notification-only. Legal review per change. Drives NFR-CONSENT-3/4.
- D-CONSENT-3 — Shadow-member ToS. ✅ A
shadowmember is created under the household admin's acceptance (admin accepts on the household's behalf at creation); the shadow member completes their own ToS/consent on activation/claim (supplements, does not replace). - D-CONSENT-4 — Re-consent SLA. ⚖️ Keep 14 days / 85% as MVP-1 draft targets: adult ToS bumps = 14-day window; child VPC bumps block child-data processing immediately on a material child-consent change until re-consent. Counsel/product confirm the numbers.
- D-CONSENT-5 — Consent-record retention. ⚖️ Retain the consent/VPC event record (proof consent existed) for the legally-required minimum after child-PII erasure — the record itself carries no child PII beyond an opaque ref. Jurisdiction-specific; counsel confirms the duration.
Out of scope (MVP-1)
- COPPA-specific data-minimization, parental review/deletion, and no-marketing controls → Children's privacy (COPPA).
- GDPR right-to-erasure on consent records, data-portability SLAs, and cross-jurisdiction retention limits → Privacy & GDPR (pre-EU launch).
- General admin audit-log surface → Audit log.
- Teen (13–17) consent flows under CCPA/CPRA or state minor-privacy laws — handled in COPPA epic or Privacy & GDPR, not here.