Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9e1449f0db | ||
|
|
0aad5394e9 | ||
|
|
6ec239d2e0 |
+11
-3
@@ -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
|
||||
|
||||
@@ -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`.
|
||||
|
||||
|
||||
@@ -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) */}
|
||||
<Route path={"/terms_of_service/"} Component={TermsOfService} />
|
||||
<Route path={"/legal/terms-of-service"} Component={PublicTermsOfServicePage} />
|
||||
{/* Play Console account-deletion URL (#103) — must stay public */}
|
||||
<Route path={"/account-deletion/"} Component={AccountDeletionPage} />
|
||||
|
||||
<Route element={<ProtectedRoutes />}>
|
||||
<Route path={"/"} index={true} Component={AsyncDashboard2} />
|
||||
|
||||
@@ -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(
|
||||
<MemoryRouter>
|
||||
<AccountDeletionPage />
|
||||
</MemoryRouter>,
|
||||
);
|
||||
|
||||
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();
|
||||
});
|
||||
});
|
||||
@@ -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 => (
|
||||
<Box sx={{ py: 4, px: 2, minHeight: '100vh', bgcolor: 'background.default' }}>
|
||||
<Card sx={{ maxWidth: 900, mx: 'auto', width: '100%' }}>
|
||||
<CardContent>
|
||||
<Typography variant="h3" component="h1" gutterBottom>
|
||||
Hesychia — Request account deletion
|
||||
</Typography>
|
||||
<Typography variant="subtitle1" color="text.secondary" gutterBottom>
|
||||
Hesychia (ai.hesychia.chat) · hesychia.ai · AI ML Operations, LLC
|
||||
</Typography>
|
||||
<Typography variant="body1" color="text.secondary">
|
||||
Use the steps below to request deletion of your Hesychia account. This page does not
|
||||
require sign-in to read.
|
||||
</Typography>
|
||||
</CardContent>
|
||||
|
||||
<Divider />
|
||||
|
||||
<CardContent>
|
||||
<Stack spacing={3}>
|
||||
<Box>
|
||||
<Typography variant="h5" component="h2" gutterBottom>
|
||||
How to delete your account
|
||||
</Typography>
|
||||
<Typography variant="body1" component="ol" sx={{ pl: 2.5, m: 0 }}>
|
||||
<li>
|
||||
Open <strong>Hesychia</strong> in the mobile app or at{' '}
|
||||
<a href="https://hesychia.ai" rel="noopener noreferrer">
|
||||
hesychia.ai
|
||||
</a>
|
||||
.
|
||||
</li>
|
||||
<li>Sign in with the account you want deleted.</li>
|
||||
<li>
|
||||
Go to <strong>Account</strong>.
|
||||
</li>
|
||||
<li>
|
||||
Choose <strong>Delete my account</strong>, then confirm by typing your account
|
||||
email.
|
||||
</li>
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<Typography variant="h5" component="h2" gutterBottom>
|
||||
What happens when you delete
|
||||
</Typography>
|
||||
|
||||
<Typography variant="h6" component="h3" gutterBottom sx={{ mt: 2 }}>
|
||||
Deactivated immediately
|
||||
</Typography>
|
||||
<Typography variant="body1" component="ul" sx={{ pl: 2.5, m: 0 }}>
|
||||
<li>Your account is marked deleted and set inactive.</li>
|
||||
<li>You lose access to Hesychia and cannot sign in again with that account.</li>
|
||||
<li>Your conversations are hidden from the product.</li>
|
||||
<li>Active sessions are invalidated (refresh tokens are blacklisted).</li>
|
||||
</Typography>
|
||||
|
||||
<Typography variant="h6" component="h3" gutterBottom sx={{ mt: 2 }}>
|
||||
Data retained after soft-delete
|
||||
</Typography>
|
||||
<Typography variant="body1" paragraph>
|
||||
Hesychia currently uses a <strong>soft-delete</strong> 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.
|
||||
</Typography>
|
||||
|
||||
<Typography variant="h6" component="h3" gutterBottom>
|
||||
Retention period
|
||||
</Typography>
|
||||
<Typography variant="body1" paragraph sx={{ mb: 0 }}>
|
||||
There is currently <strong>no automatic hard-purge schedule</strong>. 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.
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<Typography variant="h5" component="h2" gutterBottom>
|
||||
Cannot access your account?
|
||||
</Typography>
|
||||
<Typography variant="body1" paragraph>
|
||||
If you cannot sign in to complete in-app deletion, contact AI ML Operations, LLC via{' '}
|
||||
<a href="https://www.aimloperations.com" rel="noopener noreferrer">
|
||||
aimloperations.com
|
||||
</a>{' '}
|
||||
and include the email address used for your Hesychia account. We aim to respond to
|
||||
account-deletion requests within <strong>30 days</strong>.
|
||||
</Typography>
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
Staff accounts cannot self-delete in the app; use the contact path above.
|
||||
</Typography>
|
||||
</Box>
|
||||
</Stack>
|
||||
</CardContent>
|
||||
|
||||
<Divider />
|
||||
|
||||
<CardContent>
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
Already have an account?{' '}
|
||||
<Button component={RouterLink} to="/signin/" size="small">
|
||||
Sign in
|
||||
</Button>{' '}
|
||||
·{' '}
|
||||
<Button component={RouterLink} to="/account/" size="small">
|
||||
Account
|
||||
</Button>{' '}
|
||||
·{' '}
|
||||
<Button component={RouterLink} to="/terms_of_service/" size="small">
|
||||
Terms of Service
|
||||
</Button>
|
||||
</Typography>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Box>
|
||||
);
|
||||
|
||||
export default AccountDeletionPage;
|
||||
Reference in New Issue
Block a user