Store readiness: in-app account deletion, privacy policy, terms, listing copy
Closes the remaining store-compliance gaps before App Store / Play submission: - Account deletion (App Store guideline 5.1.1): DELETE /me removes the user row (usage cascades). The app exposes it through one quiet 'Account' caption link under the chat, visible only when signed in, driving two native dialogs (Sign out / Delete account with a destructive confirm) — no new views, no menus, minimalism intact. Deletion signs out and resets the app; copy notes that store subscriptions are cancelled in App Store / Play settings. - docs/store/privacy-policy.md: the complete data inventory (matching the actual schema), transient OpenAI processing with no training, no profiling or ads, GDPR legal bases and rights, in-app erasure. - docs/store/terms-of-service.md: not-therapy positioning with crisis guidance, AI-generated-content caveat, 18+ eligibility, auto-renewal/cancellation terms, liability, Swedish governing law. - docs/store/listing.md: App Store and Play copy written to the honest-claims rule (subtitle 'Think Beyond Thought', keywords, descriptions), plus App Privacy and Data safety questionnaire mappings. - LAUNCH.md updated: host the policy/terms, set store URLs, use the prepared listing copy. - Tests: 30 passing (adds DELETE /me coverage). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0118DaxZR36RpnY524vRqx3z
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
vi.mock('../src/db.js', () => ({
|
||||
deleteUser: vi.fn(),
|
||||
getOrCreateUser: vi.fn(),
|
||||
getUsage: vi.fn(),
|
||||
incrementUsage: vi.fn(),
|
||||
@@ -14,7 +15,7 @@ vi.mock('../src/subscription/index.js', () => ({
|
||||
}));
|
||||
|
||||
import { generateReply } from '../src/chat.js';
|
||||
import { getOrCreateUser, getUsage, incrementUsage } from '../src/db.js';
|
||||
import { deleteUser, getOrCreateUser, getUsage, incrementUsage } from '../src/db.js';
|
||||
import { handler } from '../src/handler.js';
|
||||
import { verifyAndApplyPurchase } from '../src/subscription/index.js';
|
||||
|
||||
@@ -101,6 +102,15 @@ describe('authorization', () => {
|
||||
});
|
||||
expect(getOrCreateUser).toHaveBeenCalledWith('sub-1', 'a@b.se', 'apple');
|
||||
});
|
||||
|
||||
it('deletes the account on DELETE /me', async () => {
|
||||
const { status, body } = await call('DELETE', '/me', {
|
||||
claims: { sub: 'sub-1', email: 'a@b.se' },
|
||||
});
|
||||
expect(status).toBe(200);
|
||||
expect(body.deleted).toBe(true);
|
||||
expect(deleteUser).toHaveBeenCalledWith('user-1');
|
||||
});
|
||||
});
|
||||
|
||||
describe('chat and the intelligent paywall', () => {
|
||||
|
||||
Reference in New Issue
Block a user