Allin — internal
Enter the password to continue.
Allin — GDPR

Allin — GDPR

What's done, what's still open, and who it's waiting on — one table to scan, details below for anyone who wants the why/where/how. Sourced from GDPR, UK-specific law, Apple's App Store rules, or Allin's own Terms/Privacy Policy (tagged per item) — checked against live code and dashboards, not the intended design. Not a solicitor's sign-off; a lawyer should confirm the borderline calls.

At a glance

Click any row to jump to its detail below
ItemStatusOwner
Done
Consent screen — 3 separate togglesBuilt
Settings → Privacy (revisit consent)Built
Analytics/ads gated behind consentBuilt
Amplitude stopped receiving emailLive
Account deletion, hardenedBuilt
Anthropic disclosed as a processorDocumented
DPIA + ROPAFiled
iOS privacy manifestFiled
Supabase, Amplitude, Apple DPAsConfirmed
Retention windowDecided — 180 days
Website pricingAlready correct
Crisis screen, ForceUpgrade, referral/review promptsBuilt
Built, not yet live
Erasure fan-out to Amplitude/Customer.ioNot deployedMarie — go to deploy
Consent audit trail (record what was granted)Not deployedMarie — go to push
Pseudonymization, Stage 1Not deployedMarie — go to push
Redacted admin viewsNot appliedMarie — go to apply
Data export + dormant-account finderNot deployedMarie — go to deploy
Corrected Privacy PolicyNot publishedIsabel to publish
Compulsory — open
DPAs: Customer.io, Meta, RevenueCat, AnthropicOpenMarie
ICO registrationNot checkedIsabel
Publish the corrected Privacy PolicyOpenIsabel to publish, both sign off
Pick the age-gate approachOpenIsabel + Marie
Confirm App Store age ratingNot checkedIsabel
Desirable — open
Pseudonymization, Stage 2 + 3DraftedMarie — watched window
Encryption at restBackend builtMarie — review iOS side
Different legal domain
Marketing claims — 2 items need wordingOpenIsabel

A few terms, in plain English

Edge function — a small piece of Allin's own server code. Migration — a saved database change; writing one doesn't apply it. Branch — a safe copy of the code; nothing on it affects real users until it's pushed and deployed. Committed, not deployed — finished and saved, not yet switched on. Database view — a limited window onto real data, for seeing patterns without seeing private text. Pseudonym — a random token standing in for an account, so data groups by "same person" without revealing who. RLS — database rules on who can see which rows.

Done

Settings → Privacy — revisit consent any time

DoneSource: GDPR Art. 7(3) — withdrawal as easy as granting
The permanent version of the same two toggles, inside Settings, for changing your mind later.

privacy & data

📈
improve the app
📣
ads
Source: Allin/Home/SettingsView.swiftPrivacyConsentView

Amplitude stopped receiving email

Done — liveSource: GDPR Art. 5(1)(c), minimization
Removed the Segment mapping that forwarded email as a User Property. The only item on this page confirmed live in production, not just committed.
Check Amplitude → User Properties on any new user — no email field. Verified against AnalyticsClient.swift's identify().

Account deletion, hardened

Done
A failed deletion used to fail silently, leaving the account fully live while the app acted like it had succeeded. Now surfaces the failure instead. Also: consent now clears on delete (not on plain sign-out), so it can't carry over to the next person on that device.
Allin/Core/AuthenticationManager.swiftdeleteAccount()

Anthropic disclosed as a processor

Done — corrected the record
recommend-plan was documented as "FTS only, no LLM" — wrong. The live app calls Claude/Anthropic on every plan generation (FTS is the fallback). Now disclosed in the DPIA, ROPA, and privacy policy draft; a signed DPA with Anthropic is the top open item as a result.

DPIA + ROPA

DoneSource: GDPR Arts. 30/35
Both complete, kept current as processors changed (Anthropic added). Living documents — comment directly in the Doc.

iOS privacy manifest

DoneSource: Apple App Store Connect, not GDPR
Apple's own submission requirement — corrected to match actual ATT-gated tracking behavior.
Allin/PrivacyInfo.xcprivacy

Processor DPAs

Data Processing Agreements — one per third party (GDPR Art. 28)
ProcessorStatusWhat's left
AppleDoneCovered by the Developer Program License Agreement.
SupabaseDoneAuto-incorporated into its Terms — confirmed directly in the dashboard, no signature needed.
AmplitudeDoneSame auto-coverage, confirmed at their Trust Center.
Customer.ioFoundNeeds actual signing (not automatic) — Marie, from her other account.
MetaNot startedMarie — paused deliberately, not blocked.
RevenueCatBlocked on loginMarie — also needs a new v2 API key while logging in.
AnthropicBlocked on loginMarie — platform.claude.com needs its own separate login.
SegmentNot checkedLower urgency — never receives special-category text.

Retention window — 180 days

DoneSource: GDPR Art. 5(1)(e)
Marie's decision: 180 days of inactivity, matching Segment's own retention for the same account. dormant_accounts() identifies accounts past this cutoff — identification only, no auto-delete yet.
allin-backend · feat/gdpr-export-retention · 20260817120000_dormant_accounts.sql

Website pricing — already correct

Done — verified live
join-allin.com states £69.99/year, matching the real App Store price — re-checked live 2026-08-19. A real mismatch once (confirmed 2026-08-14), fixed on the site since; no action needed.

Crisis screen, ForceUpgrade, review + referral prompts

Done
Four smaller shipped pieces, grouped together: Crisis support — UK users now see Shout (text) alongside Samaritans (call), region-resolved from device locale. ForceUpgradeView — restyled to match the app's real design tokens, copy unchanged. Review + referral prompts — both use Apple's native system UI, not a custom screen; only the referral message text is Allin's own (placeholder, needs Isabel + Marie sign-off).

you don't have to hold this alone

samaritans
116 123 · free, 24/7
shout new
text 85258 · free, 24/7

A new version is available

update now
Sources: CrisisResources.swift · ForceUpgradeView.swift · AppView.swiftpresentReferralShare()

Standing rule for future AI features

Design principle
For any future feature reading someone's own history through a model ("we've mapped your subconscious"): send only content, never an identifier, in either direction — identity stays Allin's own side. If a future feature needs cross-call memory, the correlation key is the pseudonym, never the real account id.

Built, not yet live

safe to ship — needs your push

Nothing below is actually live yet

Marie + Isabel — sign off, then push
All five items below are built and safe to ship, but none satisfy anything legally until they're actually protecting a real user.

Erasure fan-out to Amplitude/Customer.io

Marie — go to deploy
Account deletion only removed Allin's own rows before — never told Segment/Amplitude/Customer.io. This function fans erasure out to all three, non-fatal per-processor failure.
allin-backend · combined-fixes-2026-08-15 · delete-user-data/index.ts

Pseudonymization, Stage 1 of 3

Marie — go to push
Additive schema only — a mapping table + trigger stamping every new check-in with a random token, nothing existing can break. Stages 2/3 (below, Desirable) are what actually deliver the protection.
allin-backend · feat/gdpr-layer2-pseudonymize · 20260816000000_..._stage1.sql

Redacted admin views

Marie — go to apply
Three SQL views exposing only coarse metadata (truncated id, mood-shift direction — never free text or email), plus a restricted login role. Doesn't stop a privileged/owner login — that's what pseudonymization is for.

Data export + dormant-account finder

Marie — go to deploySource: GDPR Arts. 15/20
export-user-data returns everything Allin's own tables hold, as JSON, via a new "download my data" row in Settings. dormant_accounts() just identifies accounts past the 180-day cutoff — no deletion or notification yet.
Allin/Home/SettingsView.swiftexportMyData() · allin-backend · feat/gdpr-export-retention

Privacy Policy — corrected draft ready

Live version currently states two false things
Legal requirementSource: GDPR Arts. 12–14Isabel to publish, both sign off
The live page is publicly readable and currently false. Corrected text is ready; not yet located in the Squarespace editor.

Compulsory — open

real legal obligations

DPAs: Customer.io, Meta, RevenueCat, Anthropic

Legal requirementMarie
See the processor table above for exactly what each needs.

ICO registration

Legal requirementSource: UK Data Protection Act 2018Isabel
UK controllers must register with the ICO and pay the annual fee (~£40–60/year). Publicly checkable — one of the more commonly enforced gaps precisely because it's easy to spot.

Pick the age-gate approach

Terms state 16+; nothing enforces it
Legal exposureUK Children's Code + Allin's own T&CsIsabel + Marie
Two sources: the Children's Code applies to any service children are likely to reach, and Allin's own Terms already promise 16+ with zero enforcement behind it. Three options: rely on the App Store rating alone (weakest); self-declared birthdate, hard-block under-16 (recommended — matches what the Terms already claim); full parental-consent flow for 13–15 (most engineering).

Confirm App Store age rating still matches the content

Legal requirementSource: Apple App Review GuidelinesIsabel
Separate from the age-gate above — Apple's own content questionnaire in App Store Connect. Worth confirming it still reflects the crisis-support content and emotional-distress themes now in the app.

Desirable — open

named GDPR example measures, not mandatory on their own

Pseudonymization, Stage 2 + 3

Drafted, not appliedSource: GDPR Art. 25/32Marie — watched maintenance window
Marie's call: go all the way, not stop at Stage 1. Stage 2 backfills every row; Stage 3 drops the real account id and tightens RLS to pseudonym-only, with a safety check that refuses to run if Stage 2 isn't complete. Needs a full backup first, and a paired one-line iOS change applied at the same moment Stage 3 runs.
allin-backend · feat/gdpr-layer2-pseudonymize · stage2_backfill.sql, stage3_drop_userid.sql

Encryption at rest

Backend done, not deployedSource: GDPR Art. 32Marie — review iOS side before it ships
AES-256-GCM, key exists only as an Edge Function secret, never in Postgres. New rows would populate an encrypted column alongside the existing plaintext one. Deliberately not done yet: switching the iOS app to actually call these functions instead of writing to the table directly — that's the single most-used code path in the app, so it gets its own dedicated review.
allin-backend · feat/gdpr-encryption-at-rest

Different legal domain

not GDPR, but real

Marketing claims — 2 items need wording

Different domainSource: ASA / Consumer Protection lawIsabel
Everything else on the claims register is sourced and safe; two claims need Isabel's exact wording call.

Who does what

I

Isabel

Each item below has a ready prompt — paste it into your own Claude.

ICO registration
Prompt for your Claude
Help me check whether Allin Well Ltd is already registered with the ICO — search the public register at ico.org.uk/ESDWebPages/Search. If it's not there, walk me through registration and the data-protection-fee process at ico.org.uk/for-organisations/data-protection-fee — but don't submit anything until I confirm.
Privacy Policy — review, sign off, publish
Prompt for your Claude
Open this corrected Privacy Policy draft: https://claude.ai/code/artifact/1ab9d13b-5a0b-4efa-b2b1-ec19c0708923 — walk me through what changed vs. the live join-allin.com policy and why. Once I've said I'm happy, help me find the Privacy Policy page in Squarespace and get it ready to paste — but don't publish until I explicitly say go.
Marketing claims — 2 items need wording
Prompt for your Claude
Open the Marketing Claims Register: https://claude.ai/code/artifact/2e972533-d0ee-41be-9365-1dcafa3eb943 — 2 flagged claims need my exact wording. Walk me through each and help me draft accurate replacements.
Pick the age-gate approach (with Marie)
Prompt for your Claude
Open https://allin-gdpr.pages.dev (password Isma2026), find "Pick the age-gate approach." Walk me through the three options and trade-offs so I can bring a recommendation to Marie.
Sign off on the consent screen + release branch (with Marie)
Prompt for your Claude
Open https://allin-copy-review.pages.dev (password Isma2026) — walk me through the consent screen copy, the crisis-line addition, and the referral message, so I can approve, reject, or ask for changes on each before this ships.
Confirm the App Store age rating still matches the content
Prompt for your Claude
Help me check Allin's current App Store Connect age rating and content questionnaire, and confirm it honestly reflects the app now — including crisis-support content and emotional-distress themes.
M

Marie

Execute the Customer.io DPA from your other account · check Meta Business Manager's DPA status · log into RevenueCat to check DPA status + generate a new v2 API key · log into platform.claude.com to check Anthropic's DPA status · deploy the 5 built-not-live items above · schedule pseudonymization Stage 2/3's maintenance window · review the encryption iOS integration · age-gate approach (with Isabel) · sign off on the consent screen + release branch (with Isabel)

The full reasoning

why these are compulsory, where each source comes from, and what's left by type

How this list was built

So you can judge whether it's actually complete, not just trust it
This wasn't brainstormed — it comes from working through the standard GDPR obligation categories one at a time and checking each against Allin's actual live code and schema, not the intended design: lawful basis (what allows processing check-in/health-adjacent data at all — Art. 9 explicit consent), transparency (Arts. 12–14, the privacy policy has to be true), data subject rights (Arts. 15/17/20 — access, erasure, portability), storage limitation (Art. 5(1)(e) — a defined retention period), security (Art. 32 — pseudonymization/encryption as named example measures), accountability (Art. 30 ROPA, Art. 35 DPIA for high-risk processing), processor agreements (Art. 28 — a DPA per third party, cross-referenced against every processor actually found in the data-flow mapping), plus the UK-specific pieces (ICO registration, the Children's Code) and Apple's own separate requirements (App Store age rating, the privacy manifest) layered on top.
Four distinct sources, tagged on every item above:
  • GDPR itself — Arts. 5, 6, 7, 9, 12–14, 15, 17, 20, 25, 28, 30, 32, 35. The baseline: lawful basis, transparency, data rights, retention, security, accountability, processor agreements.
  • UK-specific law — the Data Protection Act 2018 (ICO registration + fee) and the Children's Code (applies to any service children are likely to reach, not just ones aimed at them).
  • Apple's own App Store requirements — the privacy manifest and the App Store's independent age-rating questionnaire. Neither is GDPR; both are enforced at app review, separately from anything a regulator would check.
  • Allin's own Terms & Privacy Policy — a self-imposed promise creates its own obligation to actually be true. The age-gate item is the clearest example: the Terms already state 16+ with zero enforcement behind it, which is its own accuracy problem even setting the Children's Code aside.
Several items only surfaced because the live code was checked directly rather than assumed: the consent-recording function that turned out not to actually persist anything (0 of 112 real users have a consent record), Anthropic as an undisclosed processor, the repo/live drift on recommend-plan. That's the actual basis for calling this reasonably complete — systematic obligation-by-obligation coverage, verified against what's really running, not a checklist copied from a template. Honest limit: this is a technical/product review, not a solicitor's sign-off — the borderline calls (age-gate, ICO specifics) are worth a real lawyer confirming before treating this as final.

Every action, in full — done and in progress

Written for Isabel: the complete reasoning behind each one, not a summary — so you can actually be comfortable everything real is covered

Consent screen — 3 separate toggles Done

The old flow was one low-friction button — "allow tracking and reminders" or "skip" — covering multiple different purposes (analytics, advertising, reminders) with a single yes/no. GDPR requires consent to be specific: each distinct purpose needs its own separate, informed, freely-given choice, not one blanket switch. That's why this became a genuine 3-decision screen, each toggle gettable and revocable on its own. One thing still genuinely unresolved: there's no separate decline/skip button — leaving every toggle off and tapping "continue" is the decline path, so someone who says no to everything sees the exact same button as someone who said yes. Worth your read on whether "continue" reads neutral enough either way.

Settings → Privacy screen Done

GDPR Art. 7(3) requires withdrawal to be as easy as granting — a one-time consent screen alone doesn't satisfy that. This is the permanent version inside Settings, so changing your mind later isn't buried or harder than the original choice was.

Analytics/advertising gated behind consent Done

Built alongside the consent redesign, and arguably the most important piece: AnalyticsClient/MetaAdsClient now check the stored consent state before sending anything at all, rather than sending first and hoping someone opts out later. The consent screen only matters if a "no" actually stops something from happening — this is the part that makes that true day to day, separate from being able to prove it happened (see the consent audit trail below).

Amplitude stopped receiving email Done — live

Amplitude needs a persistent reference to a person for behavioral analysis, but never needed their actual email — sending it anyway was excess data under the minimization principle (Art. 5(1)(c)), and was the single most urgent, fastest fix found across every audit on this project. Fixed by removing the Segment mapping that forwarded email as a User Property, then independently re-verified against the app's real analytics code to confirm it's actually gone, not just configured-to-be-gone. The only item on this page confirmed live in production, not just committed.

Account deletion, hardened Done

A real problem found while reviewing the erasure flow: if deletion failed partway, the failure was silently swallowed and the app proceeded exactly as if it had succeeded — meaning someone could believe they'd exercised their right to erasure while their account and data were still fully live. Pretending success is arguably worse than a visible error, since it removes the person's ability to even know something went wrong and try again. Also fixed alongside this: consent is per-account, not per-device, so it's now explicitly cleared on delete (not on plain sign-out) — otherwise a deleted account's consent could silently carry over to whoever signs up next on that device.

Anthropic disclosed as a processor Done — corrected the record

recommend-plan had been documented as "100% Postgres full-text search, no LLM call" — that was wrong. The live app activates a Claude/Anthropic composition path on every plan generation; full-text search is the fallback only. That makes Anthropic a real processor, receiving check-in and plan-intake text, that wasn't previously disclosed anywhere. Added to the DPIA, ROPA, and privacy policy draft the moment this was found — and a signed DPA with Anthropic became the single highest-priority open item as a direct result.

DPIA + ROPA Done

The foundational accountability paperwork Arts. 30/35 require for processing this kind of data at all — a data protection impact assessment and a record of processing activities. Both complete, and kept current as new processors were found rather than treated as a one-time exercise.

iOS privacy manifest Done

Distinct from the GDPR paperwork above — this is Apple's own submission requirement (declaring data collection and "required reason" API usage), enforced at app review, not a GDPR obligation. Was previously stale; corrected to match actual ATT-gated tracking behavior.

Processor DPAs — Supabase, Amplitude, Apple Done

GDPR Art. 28 requires a written agreement with anyone processing personal data on Allin's behalf — this isn't scaled by sensitivity or company size, it applies the moment a third party touches personal data at all. Apple is covered by the existing Developer Program License Agreement. Supabase and Amplitude were checked directly in each dashboard (2026-08-17) and confirmed auto-incorporated into their respective Terms of Service — no signature needed, no action required. See the table above for what's still open on Customer.io, Meta, RevenueCat, and Anthropic.

Retention window — 180 days Done

GDPR Art. 5(1)(e) requires a defined limit on how long personal data is kept — before this there was no policy at all, just indefinite storage by default. Marie's decision: 180 days of inactivity, matching Segment's own retention window for the same account, rather than an unrelated number. dormant_accounts() identifies accounts past this cutoff — identification only for now, not auto-deletion (see the nice-to-have below for turning this into a full lifecycle).

Website pricing Done — verified live

Not a GDPR item, but the same class of accuracy problem as the age-gate promise below: a stated price that doesn't match what's really charged. Was a genuine mismatch (£69 vs. the real £69.99), confirmed live 2026-08-14; re-checked directly 2026-08-19 and the site now correctly states £69.99 — fixed independently of this project, no action needed.

Crisis screen, ForceUpgrade, review + referral prompts Done

Four smaller pieces, not required by GDPR but part of the same overall safety and honesty posture: the crisis-support screen now offers Shout (text) alongside Samaritans (call) for UK users, since not everyone in crisis wants to make a phone call. ForceUpgradeView was restyled since it's the one screen most likely to actually stop a real user and previously looked like a generic placeholder. The review and referral prompts intentionally use Apple's native system UI rather than a custom screen — nothing further to build there.

Erasure fan-out to Amplitude/Customer.io Built, not live

Account deletion previously only removed Allin's own Supabase rows — it never told Segment, Amplitude, or Customer.io, so a "deleted" person's data kept living indefinitely in every third-party processor, which doesn't satisfy the right to erasure. This function fans erasure requests out to all three in parallel, then calls the existing delete_user() database function. A processor failure is logged but deliberately non-fatal — trapping someone in a "we couldn't delete your account" loop because a third-party API had a bad minute would be a worse GDPR posture than proceeding, and none of these processors delete synchronously anyway (their own stated SLAs are "within 30 days," not instant). Meta is deliberately not called here — they don't expose an API for requesting erasure of an arbitrary user, only the reverse; Allin's actual control over Meta data is upstream, in what it collects and the consent gate already in place.

Consent audit trail Built, not live

GDPR Art. 7(1) doesn't just require that consent was actually given — it requires being able to demonstrate it was, on demand. The app's own protective behavior (not sending analytics/ads without consent) was already fine, enforced separately client-side — what was missing was proof. This was discovered by reading the consent screen's real server-side behavior rather than trusting that a function with a matching name meant a working implementation: the call was wrapped in a silent try?, failing with zero visible error since the granular screen shipped. Confirmed directly against the live database: 0 of 112 real users have any consent recorded at all. The fix is a proper table plus matching functions for both the initial grant and later Settings changes.

Pseudonymization, Stage 1 of 3 Built, not live

This came directly out of a real incident, not a theoretical audit: a name was found sitting next to a private note on a live dashboard query. The redacted-views mitigation (next item) only protects when someone logs in through the restricted role — it does nothing to stop the owner or service-role login from reading identity and content together directly, which is exactly the access level that produced the incident. Getting to "even a full-privilege login sees a random token, not a person" needs the account id actually separated from the content, which is why this became staged, multi-part work rather than a single fix. Stage 1 is additive only — a mapping table and trigger, nothing existing can break.

Redacted admin views Built, not live

Pseudonymization Stage 2/3 needs a watched maintenance window and a backup before it can run — it isn't a same-night fix. This was the fast, safe thing to do in the meantime: three SQL views exposing only coarse metadata (truncated id, mood-shift direction — never free text or an email), plus a restricted login role, to reduce the everyday risk of someone glancing at a dashboard and seeing a name next to a private note. Explicitly a stopgap, not a replacement — it doesn't stop a privileged/owner login, which is exactly what pseudonymization is for.

Data export + dormant-account finder Built, not live

Two separate hard requirements bundled into one build pass. Arts. 15/20 give someone the right to access and receive a copy of their own data — until export-user-data existed, Allin had no way to honor that request at all. Art. 5(1)(e) requires a retention limit — dormant_accounts() is the identification half of that (see the Done retention card above for the decided 180-day number).

Privacy Policy — corrected draft ready Built, not live

The live policy states things that are provably false against real behavior: "Allin does not actively share personal data with third parties" (wrong — Segment routes to Amplitude/Customer.io/Meta) and "we do not collect health data" (wrong — the check-in flow literally is special-category data collection). Every other gap on this page is invisible unless someone goes looking at code or a database; this one is a public page any user, journalist, or regulator can read today and see is false, which makes it the single most exposed item here. A corrected draft was written — and a few hours later, that draft was itself found saying check-in text is "never sent to any other outside provider," which stopped being true the moment Anthropic was discovered. Corrected openly rather than quietly edited.

DPAs still open: Customer.io, Meta, RevenueCat, Anthropic Compulsory

Same Art. 28 requirement as the done processors above — these four just aren't resolved yet. Anthropic is the most urgent of the four specifically because it's the newest-confirmed processor, receiving real special-category text on every call — the least-covered flow gets the least excuse for an unsigned agreement. Customer.io is second because its DPA and terms are already fully known; it's purely an execution step away from closed. Meta and RevenueCat are lower urgency, each blocked by a distinct, named reason (a paused check, a missing login) rather than a generic "unconfirmed."

ICO registration Compulsory

UK data controllers must register with the ICO, with narrow exemptions that don't apply to a company processing special-category health-adjacent data. Unlike most items on this page, this isn't a matter of interpretation — it's a binary yes/no, checkable in seconds on the public register, which is exactly why it's one of the more commonly enforced gaps in practice: an unregistered controller is trivially easy for anyone to spot.

Pick the age-gate approach Compulsory

Two distinct sources, not one: externally, the UK Children's Code applies to any service children are likely to reach, not just ones aimed at them, and paid Meta ads mean the real audience age isn't controlled. Separately, and just as real: Allin's own Terms already state a 16+ requirement with parental consent under 18, with zero enforcement behind it — the same class of accuracy problem as the Privacy Policy's false statements, just sitting in the Terms instead. Either source alone would justify action; having both is why this sits in Compulsory rather than Desirable. Recommended approach: self-declared birthdate at signup, hard-block under-16 — lowest friction that actually makes the existing Terms wording true.

Confirm App Store age rating still matches the content Compulsory

Easy to conflate with the age-gate above, but a different authority and mechanism: Apple independently requires every app to carry an age rating based on a content questionnaire in App Store Connect, enforced at app review, separate from anything GDPR or the ICO requires. Allin now has real crisis-support content (Shout/Samaritans) and emotional-distress themes that weren't necessarily reflected in whatever rating was set at first submission.

Pseudonymization, Stage 2 + 3 Desirable

Art. 32 names pseudonymization as an example security measure, not a mandatory one on its own — GDPR requires "appropriate" security, and Stage 1 plus the redacted views already reduce everyday risk. Stages 2/3 close the gap for a full-privilege login specifically, a real and serious exposure, but a risk-reduction choice on top of the legal floor rather than the floor itself — which is why it's Marie's call on timing, not an unconditional requirement. Marie's decision was to go all the way rather than stop at Stage 1, precisely because "reduces the risk" isn't the same as "removes it."

Encryption at rest Desirable

Also a named Art. 32 example, not a standalone mandate. Pseudonymization separates who from the content; encryption protects the content itself even if someone did get to it — either alone is meaningful but partial, together they deliver "even a full-privilege login learns nothing." The iOS integration is deliberately held back from this pass since it's the single most-used code path in the app (every check-in save and load) and deserves its own dedicated review.

Marketing claims — 2 items need wording Different domain

Advertising standards and consumer protection are a genuinely different legal domain from data protection, but a public claim that overstates what Allin does is a real exposure of its own kind, worth tracking here rather than assuming "not GDPR" means "not relevant." Everything else on the claims register was checked and is defensible — these two specifically need Isabel's judgment on exact wording, not a legal determination.

What needs doing, by type

The same open items above, sorted a different way
App changes (code): deploy the 5 built-not-live items (consent audit trail, erasure fan-out, pseudonymization Stage 1, redacted admin views, export + dormant-account finder) · build the age-gate once the approach is picked · pseudonymization Stage 2/3 and encryption, if/when scheduled.
Documents filed: DPIA — done · ROPA — done · iOS privacy manifest — done (Apple requirement) · DPA paperwork — Supabase + Amplitude + Apple confirmed done, no signing needed; Customer.io found but needs actual signing; Meta + RevenueCat not started; Anthropic blocked on a separate login · ICO registration — not started, public register not yet checked.
Terms & Privacy Policy: Privacy Policy — corrected text ready, not yet published, two false live statements being replaced · Terms & Conditions — the "future versions" journaling clause already corrected to present-tense; the age-gate section is the one remaining place the Terms claim something (16+) that isn't actually true yet · website pricing — already correct, no action needed.

Nice to haves

not required by anything above — worth considering when there's time, not a compliance gap

Extend encryption-at-rest beyond check-ins

Optional
The encryption work above (Desirable, Art. 32) only covers emotional_sessions' free-text fields. beliefs_plans' intake text (life-area ratings + 4 free-text fields each) is the same sensitivity and isn't covered. Same architecture would extend cleanly — a later pass, not urgent.

A layered, plain-English summary at the top of the Privacy Policy

Optional
Beyond what Arts. 12–14 require: a 3–4 line "in plain English" summary above the full legal text, so someone can actually understand what happens to their data without reading the whole document. Common practice among privacy-conscious apps, not a legal requirement.

Turn dormant-account identification into a real lifecycle

Optional
dormant_accounts() only identifies accounts past 180 days today — it doesn't warn, and it doesn't delete. A nice-to-have, not a requirement: an actual email warning at, say, 150 days, then auto-delete at 180 if no response. Turns a passive report into something that actually reduces stored data over time.

Publish a simple public trust/security page

Optional
A short join-allin.com page summarizing data practices in plain terms (what's collected, who it's shared with, how to request deletion) — a trust signal for privacy-conscious users, not something GDPR requires beyond what the Privacy Policy already has to say.

Formalize a DPO designation and an annual DPIA/ROPA review cadence

Optional
Allin is very unlikely to be large enough to legally require a Data Protection Officer (Art. 37's thresholds are about large-scale/systematic monitoring or special-category processing "on a large scale" — arguable, not clearly triggered yet). Naming someone as the de facto contact, and diarizing a yearly DPIA/ROPA refresh rather than only updating them when a bug is found, is good practice ahead of actually needing it.

ISO 27001 / SOC 2 as a longer-term aspiration

Optional
Not remotely required at this scale, and a real undertaking — but worth naming as a direction of travel if Allin ever sells into organizations (e.g. an employer wellness benefit) that ask for it. Nothing to act on now.