Handshake & Sync
Overview
The app syncs content with the server via a single handshake request-response cycle. The server returns a manifest indicating what needs to be added, updated, or deleted.
Endpoint
POST https://kagtryxgjwavupzlmlzv.supabase.co/functions/v1/handshake
Authorization: Bearer {user_jwt_from_supabase_session}
Content-Type: application/json
Dev mode URLs:
- Emulator:
http://localhost:8080/handshake - Device:
http://{configured_ip}:8080/handshake
Sync Flow
- Speed test — 3 tests via Cloudflare CDN (1MB each), average must be >= 1.5 Mbps. If speed test server is unreachable, sync proceeds anyway.
- Build payload — analytics data, device ID, pending purchases. User ID is NOT in the payload — it is extracted from JWT on the server.
- Send handshake — POST to endpoint with JWT auth
- Receive manifest — server returns
json_manifest,ai_usage, andsubscriptiondata - Update user profile — write
ai_usageandsubscriptiontouser_profile.json - Analyze manifest — categorize courses into ADD, UPDATE, DELETE
- Progressive download — download new courses with user confirmation per course
- Batch updates — update existing courses and system JSONs
- Safe deletion — remove courses no longer in entitlements (profile updated first)
Request Payload
{
"analytics": {
"current_course": "C14ENB",
"voice": "Female",
"background": "None",
"induction": "Randomize",
"deepening": "Randomize",
"audio_usage": {
"1": {"title": "How to Use These Sessions", "no_of_plays": 1},
"2": {"title": "Release Social Anxiety", "no_of_plays": 3}
}
},
"device_id": "unique-device-identifier-string",
"purchases": [
{
"product_id": "h01enb",
"purchase_id": "GPA.1234-5678",
"platform": "android",
"status": "pending_validation"
}
]
}
Server Response
{
"json_manifest": {
"background.json": { "checksum": "a1b2c3d4...", "content": {} },
"core_segments.json": { "checksum": "e5f6g7h8...", "content": {} },
"FAQs.json": {},
"shop.json": {},
"ads.json": {},
"C14ENB.json": {}
},
"ai_usage": {
"weekly_limit_credits": 10,
"weekly_used_credits": 2,
"weekly_reset_date": "2025-12-30T00:00:00Z",
"bank_limit_credits": 100,
"bank_used_credits": 5
},
"subscription": {
"subscription_id": "sub_12345",
"subscription_type": "premium",
"status": "active",
"expiry_date": "2026-01-01T00:00:00Z",
"auto_renew": true,
"plan": "monthly-plan"
}
}
Sync Analysis Categories
| Category | Condition | Action |
|---|---|---|
| Courses to ADD | In server manifest, not local (and not disabled) | Full download with user confirmation |
| Courses to UPDATE | Checksum differs | Batch update changed files |
| Courses to DELETE | In local, not in server manifest | Safe deletion (profile first) |
| System JSONs | Checksum differs | Batch update |
Sync Phases (SyncPhase enum)
| Phase | Description |
|---|---|
analyzing |
Analyzing sync requirements |
checkingStorage |
Verifying device storage space |
waitingForUserConfirmation |
Waiting for user to confirm download |
downloadingCourse |
Downloading course files |
addingCourses |
Adding new courses to profile |
updatingSystem |
Updating system JSONs |
updatingCourses |
Updating existing courses |
deletingCourses |
Removing outdated courses |
updatingProfile |
Updating user profile |
completed |
Sync completed successfully |
failed |
Sync failed |
cancelledByUser |
User cancelled sync |
Checksum Requirements
- JSON formatting: 4-space indentation
- Line endings: CRLF (\r\n) for Windows compatibility
- Field order: LinkedHashMap preserves server field order
- Checksum method: MD5 hash of raw file bytes
JSON Processing Order
background.jsoncore_segments.jsonFAQs.jsonshop.jsonads.json- Course JSONs (alphabetical)
System JSONs (Protected)
These cannot be deleted and are always synced: ads.json, background.json, core_segments.json, FAQs.json, shop.json
Mitigations
| Concern | Risk | Mitigation |
|---|---|---|
| Download interruption | Network failure mid-download | Cancellation flag per file, direct write (no temp files), checksum verification |
| Storage space | Device full | Pre-calculate requirements with 50MB buffer, abort if insufficient |
| Speed test failure | CDN unreachable | Sync proceeds anyway, individual downloads fail gracefully |