From 9e1449f0dbf81651a256e9728f2aac2c474c87a5 Mon Sep 17 00:00:00 2001 From: Ryan Westfall Date: Tue, 4 Aug 2026 10:53:48 -0700 Subject: [PATCH] Add public account-deletion page for Google Play (#103) (#110) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary - Closes [#103](https://git.aimloperations.com/ai_ml_operations/chat_web_app/issues/103). - Adds public SPA route `/account-deletion/` (no auth) with Hesychia / `ai.hesychia.chat` branding, in-app deletion steps, soft-delete data retention copy, and a contact path (30-day SLA) for users who cannot sign in. - Documents Play Console **Account deletion URL** in `ANDROID.md` and `android/README.md` (`https://hesychia.ai/account-deletion/`, legacy host, HashRouter form). ## Notes - Retention copy matches backend soft-delete (v1): no claim of full erasure / hard purge yet. - Play Console field still needs to be set out-of-band after deploy. ## Test plan - [ ] Open `/account-deletion/` signed out — page loads (no redirect to sign-in) - [ ] Confirm steps match Account → Delete my account + email confirm - [ ] Confirm retention sections are accurate vs soft-delete - [ ] `npm run test:ci -- --testPathPattern=AccountDeletionPage` - [ ] After beta deploy, set Play Console Account deletion URL to the public HTTPS URLReviewed-on: https://git.aimloperations.com/ai_ml_operations/chat_web_app/pulls/110 --- llm-fe/ANDROID.md | 14 +- llm-fe/android/README.md | 12 +- llm-fe/src/App.tsx | 3 + .../AccountDeletionPage.test.tsx | 35 +++++ .../AccountDeletion/AccountDeletionPage.tsx | 130 ++++++++++++++++++ 5 files changed, 188 insertions(+), 6 deletions(-) create mode 100644 llm-fe/src/llm-fe/pages/AccountDeletion/AccountDeletionPage.test.tsx create mode 100644 llm-fe/src/llm-fe/pages/AccountDeletion/AccountDeletionPage.tsx diff --git a/llm-fe/ANDROID.md b/llm-fe/ANDROID.md index 5a02b1e..e409188 100644 --- a/llm-fe/ANDROID.md +++ b/llm-fe/ANDROID.md @@ -132,12 +132,20 @@ Out of band ops (not automated here): 1. Google Play developer account 2. Privacy policy URL (product site / legal) -3. Data safety form (JWT auth, chat content, analytics if Tianji runs in WebView) -4. Screenshots for phone (+ tablet if targeting) -5. Upload `.aab` to **internal testing** track before production +3. **Account deletion URL** (Data safety / Account deletion) → public page: + - Canonical: `https://hesychia.ai/account-deletion/` + - Legacy host until DNS cutover: `https://chat.aimloperations.com/account-deletion/` + - Capacitor HashRouter: `/#/account-deletion/` +4. Data safety form (JWT auth, chat content, analytics if Tianji runs in WebView) +5. Screenshots for phone (+ tablet if targeting) +6. Upload `.aab` to **internal testing** track before production + +In-app delete remains Account → **Delete my account** (`DELETE /api/user/`). The public URL +above is for Play reviewers and users who never open the app (#103). ## Related issues - [#20](https://git.aimloperations.com/ai_ml_operations/chat_web_app/issues/20) — this Android wrap - [#21](https://git.aimloperations.com/ai_ml_operations/chat_web_app/issues/21) — iOS (reuses this scaffolding) - [#22](https://git.aimloperations.com/ai_ml_operations/chat_web_app/issues/22) / [#23](https://git.aimloperations.com/ai_ml_operations/chat_web_app/issues/23) / [#24](https://git.aimloperations.com/ai_ml_operations/chat_web_app/issues/24) — auth / WS / routing +- [#103](https://git.aimloperations.com/ai_ml_operations/chat_web_app/issues/103) — Play public account-deletion URL diff --git a/llm-fe/android/README.md b/llm-fe/android/README.md index bf0a97d..9fc126d 100644 --- a/llm-fe/android/README.md +++ b/llm-fe/android/README.md @@ -107,9 +107,15 @@ Without `keystore.properties`, release builds are unsigned; debug builds do not 1. [Play Console](https://play.google.com/console) → app **Hesychia** (`ai.hesychia.chat`). 2. Complete store listing: privacy policy URL, data-safety form, screenshots. -3. **Testing → Internal testing** → create release → upload `app-release.aab`. -4. Add testers, roll out internal track, verify on devices. -5. Promote to closed / open / production only after internal QA passes. +3. Set **Account deletion URL** to the public instructions page (no sign-in required): + - `https://hesychia.ai/account-deletion/` (preferred product host) + - or `https://chat.aimloperations.com/account-deletion/` until hesychia.ai cutover +4. **Testing → Internal testing** → create release → upload `app-release.aab`. +5. Add testers, roll out internal track, verify on devices. +6. Promote to closed / open / production only after internal QA passes. + +See also [`../ANDROID.md`](../ANDROID.md) Play checklist and issue +[#103](https://git.aimloperations.com/ai_ml_operations/chat_web_app/issues/103). Each new upload needs a higher `versionCode`. diff --git a/llm-fe/src/App.tsx b/llm-fe/src/App.tsx index 53e2567..2f94967 100644 --- a/llm-fe/src/App.tsx +++ b/llm-fe/src/App.tsx @@ -11,6 +11,7 @@ import NotFound from './llm-fe/pages/NotFound/NotFound'; import { AuthContext } from './llm-fe/contexts/AuthContext'; import TermsOfService from './llm-fe/pages/TermsOfService/TermsOfService'; import PublicTermsOfServicePage from './llm-fe/pages/TermsOfService/PublicTermsOfServicePage'; +import AccountDeletionPage from './llm-fe/pages/AccountDeletion/AccountDeletionPage'; import SetPassword from './llm-fe/components/SetPassword/SetPassword'; import AsyncDashboard2 from './llm-fe/pages/AsyncDashboard2/AsyncDashboard2'; import FeedbackPage2 from './llm-fe/pages/FeedbackPage2/FeedbackPage2'; @@ -71,6 +72,8 @@ class App extends Component { {/* Public legal pages (also used for post-login ToS acknowledge) */} + {/* Play Console account-deletion URL (#103) — must stay public */} + }> diff --git a/llm-fe/src/llm-fe/pages/AccountDeletion/AccountDeletionPage.test.tsx b/llm-fe/src/llm-fe/pages/AccountDeletion/AccountDeletionPage.test.tsx new file mode 100644 index 0000000..6c350f3 --- /dev/null +++ b/llm-fe/src/llm-fe/pages/AccountDeletion/AccountDeletionPage.test.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import { MemoryRouter } from 'react-router-dom'; +import { render, screen } from '@testing-library/react'; +import AccountDeletionPage from './AccountDeletionPage'; + +describe('AccountDeletionPage', () => { + it('renders Hesychia deletion steps and retention copy without auth', () => { + render( + + + , + ); + + expect( + screen.getByRole('heading', { name: /Hesychia — Request account deletion/i }), + ).toBeInTheDocument(); + expect(screen.getByText(/ai\.hesychia\.chat/i)).toBeInTheDocument(); + expect( + screen.getByRole('heading', { name: /How to delete your account/i }), + ).toBeInTheDocument(); + expect(screen.getByText(/Delete my account/i)).toBeInTheDocument(); + expect( + screen.getByRole('heading', { name: /Deactivated immediately/i }), + ).toBeInTheDocument(); + expect( + screen.getByRole('heading', { name: /Data retained after soft-delete/i }), + ).toBeInTheDocument(); + expect(screen.getByRole('heading', { name: /Retention period/i })).toBeInTheDocument(); + expect(screen.getByText(/no automatic hard-purge schedule/i)).toBeInTheDocument(); + expect( + screen.getByRole('heading', { name: /Cannot access your account/i }), + ).toBeInTheDocument(); + expect(screen.getByText(/30 days/i)).toBeInTheDocument(); + }); +}); diff --git a/llm-fe/src/llm-fe/pages/AccountDeletion/AccountDeletionPage.tsx b/llm-fe/src/llm-fe/pages/AccountDeletion/AccountDeletionPage.tsx new file mode 100644 index 0000000..de5f78f --- /dev/null +++ b/llm-fe/src/llm-fe/pages/AccountDeletion/AccountDeletionPage.tsx @@ -0,0 +1,130 @@ +import React from 'react'; +import { Box, Button, Card, CardContent, Divider, Stack, Typography } from '@mui/material'; +import { Link as RouterLink } from 'react-router-dom'; + +/** + * Public Play / App Store account-deletion instructions (#103). + * No auth required — reviewers and signed-out users must be able to read this page. + */ +const AccountDeletionPage = (): JSX.Element => ( + + + + + Hesychia — Request account deletion + + + Hesychia (ai.hesychia.chat) · hesychia.ai · AI ML Operations, LLC + + + Use the steps below to request deletion of your Hesychia account. This page does not + require sign-in to read. + + + + + + + + + + How to delete your account + + +
  • + Open Hesychia in the mobile app or at{' '} + + hesychia.ai + + . +
  • +
  • Sign in with the account you want deleted.
  • +
  • + Go to Account. +
  • +
  • + Choose Delete my account, then confirm by typing your account + email. +
  • +
    +
    + + + + What happens when you delete + + + + Deactivated immediately + + +
  • Your account is marked deleted and set inactive.
  • +
  • You lose access to Hesychia and cannot sign in again with that account.
  • +
  • Your conversations are hidden from the product.
  • +
  • Active sessions are invalidated (refresh tokens are blacklisted).
  • +
    + + + Data retained after soft-delete + + + Hesychia currently uses a soft-delete process. After you delete your + account, personal data associated with the account (including profile details, + conversation content, uploaded documents / RAG vectors, and authentication event + records) may remain in our systems for administration, security, and audit purposes. + This is not a full erasure of all stored data. + + + + Retention period + + + There is currently no automatic hard-purge schedule. Soft-deleted + data is retained until a future purge process is implemented or until we process a + separate retention / erasure request through the contact path below. We will not claim + complete erasure while soft-delete-only remains in effect. + +
    + + + + Cannot access your account? + + + If you cannot sign in to complete in-app deletion, contact AI ML Operations, LLC via{' '} + + aimloperations.com + {' '} + and include the email address used for your Hesychia account. We aim to respond to + account-deletion requests within 30 days. + + + Staff accounts cannot self-delete in the app; use the contact path above. + + +
    +
    + + + + + + Already have an account?{' '} + {' '} + ·{' '} + {' '} + ·{' '} + + + +
    +
    +); + +export default AccountDeletionPage;