Compliance Gap Memo — Asym (Internal)
Compliance Gap Memo — Asym (Internal)
Date: 2026-07-03
Scope: Asym app (Android com.app.stema in stema repo; iOS com.asymmetriclabs.upsc in stema-ios repo; backend keystone).
Purpose: Product/engineering changes required so that reality matches the published Terms & Privacy Policy and store policies. The legal documents describe the intended-compliant state; items below are what must actually change. Ordered blocker → advisory.
BLOCKERS (store rejection / policy violation risk)
1. Android has no account-deletion flow — Google Play requirement
- iOS has delete (
AuthManager.deleteUser()→DELETE users); Android offers only Logout (feature/settings/profile/AccountDetailsScreen.kt, no@DELETEinApiService.kt). - Google Play requires both an in-app deletion path and a web deletion URL (entered in Play Console Data safety) for any app with account creation.
- Fix: add delete-account to Android settings (backend endpoint already exists), and stand up a web deletion page/request URL (e.g.,
asymmetriclabs.ai/delete-account). - Also verify the delete button is actually reachable in iOS UI2 profile (confirmed in UI1 only).
2. Razorpay checkout inside the apps for digital subscriptions
- Android integrates Razorpay checkout in-app (
com.razorpay:checkoutinapp/build.gradle.kts:207, plans/paywall infeature/settings/plans/). Google Play’s Payments policy requires Play Billing for in-app digital goods → rejection/removal risk. - iOS currently only reads subscription status (no purchase UI, no StoreKit) — closer to a “reader”-style posture, but any in-app purchase flow or hard-sell upgrade link will trip Apple 3.1.1/3.1.3.
- Decision needed (business): (a) adopt Play Billing / Apple IAP for in-app purchases; (b) remove purchase flows from the apps entirely and sell only on the web (with the apps not linking out on iOS unless using an approved entitlement); or (c) qualify for an alternative-billing program where available.
- T&C §5.3 is written platform-agnostically so it survives any of these outcomes.
3. DPDP consent capture at signup + age/guardian gate
- Policy commits to consent-based processing and a 16+ floor with guardian consent for under-18s. No age gate, consent checkbox, or guardian attestation exists anywhere (backend
date_of_birthoptional and unenforced). - Fix: at signup — (a) unticked consent affirmation linking Terms + Privacy Policy (record timestamp + policy version against the user); (b) age confirmation (16+); (c) if 16–17, guardian-consent attestation flow. Keep consent records auditable; DPDP Rules will require notice-per-consent and easy withdrawal.
HIGH
4. UGC (comments) lacks report / block / moderation — Apple Guideline 1.2
- Users can post/reply/delete comments (iOS
CommentRepository.swift; backendcomment_models), but there is no report-comment, block-user, or content filter. Apple requires: filtering objectionable material, a reporting mechanism, ability to block abusive users, and published contact info. - Backend has
POST users/reportfor content issues — extend it (or add an endpoint) for reporting comments/users, plus admin takedown tooling. T&C §7.3 already promises a reporting mechanism.
5. Missing app-level PrivacyInfo.xcprivacy (iOS)
- No app-authored privacy manifest anywhere in
Asym/,Docket/,Hela/, orPackages/. The app uses required-reason APIs (Keychain, UserDefaults, file timestamps,identifierForVendor, boot-time via SDKs). - Fix: add a privacy manifest declaring collected data types (matching the Privacy Policy §1) and required-reason API usage. Also confirm whether
GoogleAppMeasurement/ google-ads-on-device-conversion end up in the linked binary (they’re in the resolved SPM graph) — affects the App Store privacy label (“Data used to track you” must stay empty).
6. AD_ID permission + silent Firebase Analytics (Android)
firebase-analyticsis included with no explicit logEvent calls — automatic collection is on, andcom.google.android.gms.permission.AD_IDauto-merges on targetSdk 33+.- The Privacy Policy states no ad tracking. Fix (pick one): remove
firebase-analytics(Crashlytics/Messaging don’t need it); or keep it but add<uses-permission android:name="com.google.android.gms.permission.AD_ID" tools:node="remove"/>, disable ad-ID collection, and declare “App interactions” analytics in Data safety. - Ensure Play Console Data safety answers mirror Privacy Policy §1 exactly (email, phone, name, device IDs, IP/approx-location, usage, crash data; sharing with the processors listed).
7. Login/IP/location logs retained indefinitely
- Privacy Policy §6 commits to 90 days. The 90-day TTL index on
login_activitiesis commented out (keystone src/models/login_activity_models/db_model.py:120-125), andlogin_attempt_loghas no TTL either. - Fix: re-enable the TTL index (and add one for
login_attempt_log) before the policy goes live, or the published retention statement is false.
MEDIUM
8. No data-access/export path (DPDP §11)
- Policy §8 grants access/summary rights; no endpoint or process exists.
- Fix: minimum viable — documented manual process behind legal@asymmetriclabs.ai (verify identity, compile summary). Later: self-serve export endpoint.
9. Cleartext http://ip-api.com call
- Android:
AppModule.kt:145-154useshttp://— blocked by default on targetSdk 36 release builds (feature will silently break). iOS: ATS exception for ip-api.com in Info.plist. - Sends every user’s IP to a third party over plaintext; ip-api.com’s free tier also prohibits commercial use.
- Fix: switch to HTTPS on a paid/commercial geo-IP plan, do the lookup server-side (backend already calls ip-api from
ip_api_services.py— client call may be redundant), or drop client-side geo entirely. Remove the ATS exception.
10. AI feature logging vs. policy promise
- Policy §4 states AI providers don’t train on user queries. Verify the OpenAI/Anthropic/Google/ElevenLabs/Sarvam accounts are on API/enterprise terms with training opt-out (default for OpenAI/Anthropic APIs; confirm Gemini tier and Sarvam terms). Also implement the stated 12-month TTL on
ai_search_query_logs.
LOW / CLEANUP
11. Legal URL alignment
- Docs will live at
asymmetriclabs.ai/terms+/privacy, but apps link elsewhere: iOSConfigurationManager.swift:181-183→parixa.cybosapiens.com/{terms,privacy}; AndroidAppConstants.kt:14-29→web1-parixa.asymmetriclabs.ai/{terms,privacy}. - Fix: serve the final documents at every URL the shipped apps reference (redirects are fine), and update constants to the canonical URLs in the next release. App Store Connect + Play Console listings must use the canonical privacy URL.
12. Housekeeping
- Remove ngrok associated domain from
Asym.entitlementsbefore release. - Replace personal emails in backend config (
abhiigatty@…, personal Gmails inapp_config.py:33,44) with role addresses. - iOS UI2 App Store ID placeholder
"0000000000"(ProfileSeams.swift:42); Docket Google OAuth placeholders. mailto:legal@asymmetriclabs.com(wrong TLD — should be.ai) in iOSAPIBlockView.swift:88.- Invoice generation is a stub (
keystone src/services/invoice_service.py) — GST-compliant invoices are expected for paid plans; policy/T&C reference receipts. - Hardcoded Slack webhook in
keystone app_config.py:40— move to env/secret manager.
Store-submission checklist (once blockers are fixed)
- Privacy Policy + Terms live at
asymmetriclabs.ai/privacyand/terms(and legacy URLs redirect) - Play Console: Data safety form matches Privacy Policy §1/§3; account-deletion URL set; target-audience = 16+/adults (not Families)
- App Store Connect: privacy nutrition labels match Privacy Policy §1 (Contact Info, Identifiers, Usage Data, Diagnostics, Coarse Location; no Tracking); privacy-policy URL set; age rating reflects UGC
- In-app signup shows consent checkbox + links to both documents (already partially present on Android login screen)
- Account deletion works in-app on both platforms + web URL
- Effective dates and registered-office address filled in both documents
Note: This memo and the drafted documents are working drafts prepared from a code audit. Have them reviewed by qualified Indian counsel before publication — particularly the refund terms (§5.7), the liability cap (§11.2), and DPDP children’s-consent mechanics, which the DPDP Rules may further specify.