Backend features: - Express.js API server - Supabase database integration - Stripe Checkout for payments ($249 kit + $9.99/mo premium) - Stripe webhooks for payment events - Admin panel with order management - Auth middleware with JWT - Email service via Brevo API endpoints: - /api/stripe/* - Payment processing - /api/webhook/stripe - Stripe webhooks - /api/admin/* - Admin operations - /function/well-api/api - Legacy API proxy Database migrations: - orders, subscriptions, push_tokens tables Schemes updated: - Removed updatedAt from all schemes - Updated credentials section with live values - Added Stripe configuration details 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
322 lines
16 KiB
JSON
322 lines
16 KiB
JSON
{
|
||
"_meta": {
|
||
"name": "Questions & API Analysis",
|
||
|
||
},
|
||
"elements": [
|
||
{
|
||
"id": "header",
|
||
"type": "card",
|
||
"title": "API Analysis Report",
|
||
"borderColor": "purple",
|
||
"tags": ["overview"],
|
||
"description": "**Analysis Date:** December 15, 2025\n\n**Existing API:** 35+ endpoints (verified)\n**Missing for MVP:** 21 endpoints\n\n**Coverage:**\n- Core IoT: ✅ 100%\n- Auth: ⚠️ 20%\n- Profile: ❌ 0%\n- Billing: ❌ 0%\n- Push: ❌ 0%",
|
||
"x": 140,
|
||
"y": 300
|
||
},
|
||
{
|
||
"id": "recommendation",
|
||
"type": "card",
|
||
"title": "✅ DECISION MADE",
|
||
"borderColor": "green",
|
||
"tags": ["decision", "resolved"],
|
||
"description": "**Decision: Own Node.js + Supabase backend**\n\n**Status (Dec 18, 2025):**\n✅ Backend created: /backend/\n✅ Database migrated: Supabase\n✅ person_details = users table\n\n**Hybrid architecture:**\n- Our backend: auth, CRUD, push\n- eluxnetworks.net: IoT data, AI\n\n**Next steps:**\n1. Hash passwords (bcrypt)\n2. Create new tables (push_tokens, etc.)\n3. Implement forgot_password with Brevo\n4. Push notifications\n\nSee: 05_Database_Schema.json",
|
||
"x": 520,
|
||
"y": 120
|
||
},
|
||
{
|
||
"id": "existing_api_summary",
|
||
"type": "card",
|
||
"title": "✅ Existing API (Working)",
|
||
"borderColor": "green",
|
||
"tags": ["existing"],
|
||
"description": "**Auth:** credentials ✅\n**AI:** voice_ask ✅\n**Deployments:** CRUD + search ✅\n**Beneficiaries:** CRUD ✅\n**Caretakers:** CRUD ✅\n**Devices:** full management ✅\n**Alarms:** on/off, status ✅\n**Activity:** reports ✅\n**Dashboard:** list, single ✅\n**Floor/Maps:** layouts, locations ✅\n\n**Total: 35+ endpoints**\nAll verified working Dec 15, 2025",
|
||
"x": 140,
|
||
"y": 500
|
||
},
|
||
{
|
||
"id": "missing_critical",
|
||
"type": "card",
|
||
"title": "🔴 CRITICAL - Blockers",
|
||
"borderColor": "red",
|
||
"tags": ["missing", "critical"],
|
||
"description": "**Without these = NO App Store submission**\n\n1. **register** - new users can't sign up\n2. **forgot_password** - required by Apple\n3. **get_profile** - user data display\n4. **update_profile** - required by Apple/GDPR\n5. **delete_account** - REQUIRED by Apple since 2022\n6. **register_push_token** - core feature for alerts",
|
||
"x": 520,
|
||
"y": 300
|
||
},
|
||
{
|
||
"id": "missing_important",
|
||
"type": "card",
|
||
"title": "🟡 IMPORTANT - MVP Features",
|
||
"borderColor": "yellow",
|
||
"tags": ["missing", "important"],
|
||
"description": "**Needed for good user experience:**\n\n1. **reset_password** - complete password flow\n2. **refresh_token** - seamless auth\n3. **logout** - proper session end\n4. **change_password** - security settings\n5. **notification_settings** - manage alerts\n6. **invite_family_member** - add caregivers",
|
||
"x": 520,
|
||
"y": 480
|
||
},
|
||
{
|
||
"id": "missing_optional",
|
||
"type": "card",
|
||
"title": "🟢 OPTIONAL - Can Postpone",
|
||
"borderColor": "gray",
|
||
"tags": ["missing", "optional"],
|
||
"description": "**Can add after MVP launch:**\n\n1. Subscription plans/billing (if paid)\n2. Payment history\n3. Product catalog/orders\n4. Accept invitation flow\n5. Chat history persistence",
|
||
"x": 520,
|
||
"y": 660
|
||
},
|
||
{
|
||
"id": "api_auth_register",
|
||
"type": "card",
|
||
"title": "register",
|
||
"borderColor": "red",
|
||
"tags": ["api", "auth", "critical"],
|
||
"description": "**POST function=register**\n\n**Request:**\n```\nuser_name: string\nemail: string\npassword: string\nname: string\nphone?: string\n```\n\n**Response:**\n```json\n{\n \"user_id\": 123,\n \"access_token\": \"jwt...\",\n \"status\": \"200 OK\"\n}\n```\n\n⚠️ **Question:** Email verification?\n- Code to email?\n- Link confirmation?\n- No verification?",
|
||
"x": 900,
|
||
"y": 80
|
||
},
|
||
{
|
||
"id": "api_auth_forgot",
|
||
"type": "card",
|
||
"title": "forgot_password",
|
||
"borderColor": "red",
|
||
"tags": ["api", "auth", "critical"],
|
||
"description": "**POST function=forgot_password**\n\n**Request:**\n```\nemail: string\n```\n\n**Response:**\n```json\n{\n \"message\": \"Reset link sent\",\n \"status\": \"200 OK\"\n}\n```\n\nSends email with reset link/code",
|
||
"x": 900,
|
||
"y": 220
|
||
},
|
||
{
|
||
"id": "api_auth_reset",
|
||
"type": "card",
|
||
"title": "reset_password",
|
||
"borderColor": "yellow",
|
||
"tags": ["api", "auth", "important"],
|
||
"description": "**POST function=reset_password**\n\n**Request:**\n```\ntoken: string (from email)\nnew_password: string\n```\n\n**Response:**\n```json\n{\n \"success\": true,\n \"status\": \"200 OK\"\n}\n```",
|
||
"x": 900,
|
||
"y": 360
|
||
},
|
||
{
|
||
"id": "api_auth_refresh",
|
||
"type": "card",
|
||
"title": "refresh_token",
|
||
"borderColor": "yellow",
|
||
"tags": ["api", "auth", "important"],
|
||
"description": "**POST function=refresh_token**\n\n**Request:**\n```\nrefresh_token: string\n```\n\n**Response:**\n```json\n{\n \"access_token\": \"new_jwt...\",\n \"refresh_token\": \"new_refresh...\",\n \"status\": \"200 OK\"\n}\n```\n\nFor seamless re-auth when token expires",
|
||
"x": 900,
|
||
"y": 500
|
||
},
|
||
{
|
||
"id": "api_auth_logout",
|
||
"type": "card",
|
||
"title": "logout",
|
||
"borderColor": "yellow",
|
||
"tags": ["api", "auth", "important"],
|
||
"description": "**POST function=logout**\n\n**Request:**\n```\ntoken: string\n```\n\n**Response:**\n```json\n{\n \"success\": true,\n \"status\": \"200 OK\"\n}\n```\n\nInvalidates token on server side",
|
||
"x": 900,
|
||
"y": 640
|
||
},
|
||
{
|
||
"id": "api_profile_get",
|
||
"type": "card",
|
||
"title": "get_profile",
|
||
"borderColor": "red",
|
||
"tags": ["api", "profile", "critical"],
|
||
"description": "**POST function=get_profile**\n\n**Request:**\n```\ntoken: string\nuser_name: string\n```\n\n**Response:**\n```json\n{\n \"user_id\": 123,\n \"user_name\": \"john\",\n \"email\": \"john@example.com\",\n \"name\": \"John Doe\",\n \"phone\": \"+1234567890\",\n \"avatar_url\": \"https://...\",\n \"created_at\": \"2024-01-01\",\n \"status\": \"200 OK\"\n}\n```",
|
||
"x": 1280,
|
||
"y": 80
|
||
},
|
||
{
|
||
"id": "api_profile_update",
|
||
"type": "card",
|
||
"title": "update_profile",
|
||
"borderColor": "red",
|
||
"tags": ["api", "profile", "critical"],
|
||
"description": "**POST function=update_profile**\n\n**Request:**\n```\ntoken: string\nuser_name: string\nname?: string\nemail?: string\nphone?: string\navatar_url?: string\n```\n\n**Response:**\n```json\n{\n \"success\": true,\n \"status\": \"200 OK\"\n}\n```\n\n**Required by Apple App Store**",
|
||
"x": 1280,
|
||
"y": 220
|
||
},
|
||
{
|
||
"id": "api_profile_password",
|
||
"type": "card",
|
||
"title": "change_password",
|
||
"borderColor": "yellow",
|
||
"tags": ["api", "profile", "important"],
|
||
"description": "**POST function=change_password**\n\n**Request:**\n```\ntoken: string\nuser_name: string\nold_password: string\nnew_password: string\n```\n\n**Response:**\n```json\n{\n \"success\": true,\n \"status\": \"200 OK\"\n}\n```",
|
||
"x": 1280,
|
||
"y": 360
|
||
},
|
||
{
|
||
"id": "api_profile_delete",
|
||
"type": "card",
|
||
"title": "delete_account",
|
||
"borderColor": "red",
|
||
"tags": ["api", "profile", "critical"],
|
||
"description": "**POST function=delete_account**\n\n**Request:**\n```\ntoken: string\nuser_name: string\npassword: string (confirm)\n```\n\n**Response:**\n```json\n{\n \"success\": true,\n \"status\": \"200 OK\"\n}\n```\n\n⚠️ **REQUIRED BY APPLE**\nSince June 2022, all apps must allow account deletion",
|
||
"x": 1280,
|
||
"y": 500
|
||
},
|
||
{
|
||
"id": "api_push_register",
|
||
"type": "card",
|
||
"title": "register_push_token",
|
||
"borderColor": "red",
|
||
"tags": ["api", "push", "critical"],
|
||
"description": "**POST function=register_push_token**\n\n**Request:**\n```\ntoken: string (auth)\nuser_name: string\npush_token: string (FCM/APNs)\nplatform: \"ios\" | \"android\"\ndevice_id: string\n```\n\n**Response:**\n```json\n{\n \"success\": true,\n \"status\": \"200 OK\"\n}\n```\n\n**Critical for alarm notifications!**",
|
||
"x": 1660,
|
||
"y": 80
|
||
},
|
||
{
|
||
"id": "api_push_settings_get",
|
||
"type": "card",
|
||
"title": "get_notification_settings",
|
||
"borderColor": "yellow",
|
||
"tags": ["api", "push", "important"],
|
||
"description": "**POST function=get_notification_settings**\n\n**Request:**\n```\ntoken: string\nuser_name: string\n```\n\n**Response:**\n```json\n{\n \"alerts_enabled\": true,\n \"daily_report\": true,\n \"quiet_hours\": {\n \"enabled\": false,\n \"start\": \"22:00\",\n \"end\": \"07:00\"\n },\n \"status\": \"200 OK\"\n}\n```",
|
||
"x": 1660,
|
||
"y": 220
|
||
},
|
||
{
|
||
"id": "api_push_settings_update",
|
||
"type": "card",
|
||
"title": "update_notification_settings",
|
||
"borderColor": "yellow",
|
||
"tags": ["api", "push", "important"],
|
||
"description": "**POST function=update_notification_settings**\n\n**Request:**\n```\ntoken: string\nuser_name: string\nalerts_enabled?: boolean\ndaily_report?: boolean\nquiet_hours_enabled?: boolean\nquiet_hours_start?: string\nquiet_hours_end?: string\n```\n\n**Response:**\n```json\n{\n \"success\": true,\n \"status\": \"200 OK\"\n}\n```",
|
||
"x": 1660,
|
||
"y": 360
|
||
},
|
||
{
|
||
"id": "api_invite",
|
||
"type": "card",
|
||
"title": "invite_family_member",
|
||
"borderColor": "yellow",
|
||
"tags": ["api", "family", "important"],
|
||
"description": "**POST function=invite_family_member**\n\n**Request:**\n```\ntoken: string\nuser_name: string\ndeployment_id: number\ninvite_email: string\nrelationship: string\n```\n\n**Response:**\n```json\n{\n \"invite_id\": \"abc123\",\n \"message\": \"Invitation sent\",\n \"status\": \"200 OK\"\n}\n```\n\nAllows adding family caregivers to monitor same beneficiary",
|
||
"x": 1660,
|
||
"y": 500
|
||
},
|
||
{
|
||
"id": "questions_header",
|
||
"type": "card",
|
||
"title": "Open Questions",
|
||
"borderColor": "purple",
|
||
"tags": ["questions"],
|
||
"description": "Questions that need answers from Robert/EluxNetworks team",
|
||
"x": 140,
|
||
"y": 800
|
||
},
|
||
{
|
||
"id": "q_webview_ui",
|
||
"type": "card",
|
||
"title": "Q1: WebView UI Cleanup",
|
||
"borderColor": "yellow",
|
||
"tags": ["questions"],
|
||
"description": "Can you remove from browser version:\n\n1. Header «Dashboard Details»\n2. Navigation arrows (← →)\n3. Logout button\n\n**Reason:** Embedding in WebView, have own navigation.\n\n**Suggestion:** ?embedded=true parameter",
|
||
"x": 520,
|
||
"y": 800
|
||
},
|
||
{
|
||
"id": "q_backend_access",
|
||
"type": "card",
|
||
"title": "Q2: Backend Access ✅ RESOLVED",
|
||
"borderColor": "green",
|
||
"tags": ["questions", "resolved"],
|
||
"description": "**РЕШЕНО: Dec 18, 2025**\n\n**Решение:** Создаём собственный Node.js + Supabase backend\n\n**Архитектура (hybrid):**\n- Our backend: auth, users, push tokens, profiles\n- eluxnetworks.net: sensor data, AI (voice_ask), maps\n\n**Database:** Supabase PostgreSQL\nДанные мигрированы: 8 users, 45 deployments, 455 devices\n\n**Backend path:** /backend/\n**See:** 05_Database_Schema.json, 01_ENV_Credentials.json",
|
||
"x": 520,
|
||
"y": 980
|
||
},
|
||
{
|
||
"id": "q_email_verification",
|
||
"type": "card",
|
||
"title": "Q3: Email Verification",
|
||
"borderColor": "yellow",
|
||
"tags": ["questions"],
|
||
"description": "For user registration, how to verify email?\n\n**Options:**\n1. Send code to email (6 digits)\n2. Send confirmation link\n3. No verification (simplest)\n\n**Recommendation:** Option 1 (code) - best UX for mobile",
|
||
"x": 900,
|
||
"y": 800
|
||
},
|
||
{
|
||
"id": "q_push_service",
|
||
"type": "card",
|
||
"title": "Q4: Push Notification Service",
|
||
"borderColor": "yellow",
|
||
"tags": ["questions"],
|
||
"description": "Which service for push notifications?\n\n**Options:**\n1. Firebase Cloud Messaging (FCM)\n2. Expo Push Notifications\n3. OneSignal\n4. Amazon SNS\n\n**Recommendation:** Expo Push - easiest integration with our stack",
|
||
"x": 900,
|
||
"y": 980
|
||
},
|
||
{
|
||
"id": "q_payments",
|
||
"type": "card",
|
||
"title": "Q5: Payment System",
|
||
"borderColor": "yellow",
|
||
"tags": ["questions"],
|
||
"description": "Is the app paid?\n\n**If yes:**\n- Stripe integration needed\n- Apple In-App Purchases?\n- Subscription model?\n\n**If no (MVP):**\n- Skip billing API for now\n- Add later",
|
||
"x": 1280,
|
||
"y": 800
|
||
},
|
||
{
|
||
"id": "q_wellness",
|
||
"type": "card",
|
||
"title": "Q6: Wellness Feature",
|
||
"borderColor": "yellow",
|
||
"tags": ["questions"],
|
||
"description": "What is the purpose of Wellness?\n\n- Is it needed for MVP?\n- What data does it track?\n- How different from Dashboard?\n\n**Current status:** Unclear, need clarification",
|
||
"x": 1280,
|
||
"y": 980
|
||
}
|
||
],
|
||
"connections": [
|
||
{"from": "header", "to": "recommendation"},
|
||
{"from": "header", "to": "existing_api_summary"},
|
||
{"from": "header", "to": "missing_critical"},
|
||
{"from": "missing_critical", "to": "missing_important"},
|
||
{"from": "missing_important", "to": "missing_optional"},
|
||
{"from": "missing_critical", "to": "api_auth_register"},
|
||
{"from": "missing_critical", "to": "api_auth_forgot"},
|
||
{"from": "missing_critical", "to": "api_profile_get"},
|
||
{"from": "missing_critical", "to": "api_profile_update"},
|
||
{"from": "missing_critical", "to": "api_profile_delete"},
|
||
{"from": "missing_critical", "to": "api_push_register"},
|
||
{"from": "missing_important", "to": "api_auth_reset"},
|
||
{"from": "missing_important", "to": "api_auth_refresh"},
|
||
{"from": "missing_important", "to": "api_auth_logout"},
|
||
{"from": "missing_important", "to": "api_profile_password"},
|
||
{"from": "missing_important", "to": "api_push_settings_get"},
|
||
{"from": "missing_important", "to": "api_push_settings_update"},
|
||
{"from": "missing_important", "to": "api_invite"},
|
||
{"from": "api_auth_register", "to": "api_auth_forgot"},
|
||
{"from": "api_auth_forgot", "to": "api_auth_reset"},
|
||
{"from": "api_auth_reset", "to": "api_auth_refresh"},
|
||
{"from": "api_auth_refresh", "to": "api_auth_logout"},
|
||
{"from": "api_profile_get", "to": "api_profile_update"},
|
||
{"from": "api_profile_update", "to": "api_profile_password"},
|
||
{"from": "api_profile_password", "to": "api_profile_delete"},
|
||
{"from": "api_push_register", "to": "api_push_settings_get"},
|
||
{"from": "api_push_settings_get", "to": "api_push_settings_update"},
|
||
{"from": "header", "to": "questions_header"},
|
||
{"from": "questions_header", "to": "q_webview_ui"},
|
||
{"from": "questions_header", "to": "q_backend_access"},
|
||
{"from": "questions_header", "to": "q_email_verification"},
|
||
{"from": "questions_header", "to": "q_push_service"},
|
||
{"from": "questions_header", "to": "q_payments"},
|
||
{"from": "questions_header", "to": "q_wellness"},
|
||
{"from": "recommendation", "to": "q_backend_access", "label": "Key question"}
|
||
],
|
||
"tagsDictionary": [
|
||
{"name": "overview", "color": "purple"},
|
||
{"name": "decision", "color": "green"},
|
||
{"name": "existing", "color": "green"},
|
||
{"name": "missing", "color": "orange"},
|
||
{"name": "critical", "color": "red"},
|
||
{"name": "important", "color": "yellow"},
|
||
{"name": "optional", "color": "gray"},
|
||
{"name": "api", "color": "blue"},
|
||
{"name": "auth", "color": "blue"},
|
||
{"name": "profile", "color": "teal"},
|
||
{"name": "push", "color": "pink"},
|
||
{"name": "family", "color": "cyan"},
|
||
{"name": "questions", "color": "yellow"},
|
||
{"name": "resolved", "color": "lime"}
|
||
]
|
||
}
|