WellNuo/wellnuoSheme/05_Database_Schema.json
Sergei 3c8a9fc336 Add Node.js backend with Stripe integration and admin panel
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>
2025-12-19 09:49:24 -08:00

201 lines
12 KiB
JSON

{
"_meta": {
"name": "Database Schema",
},
"elements": [
{
"id": "header",
"type": "card",
"title": "WellNuo Database Schema",
"borderColor": "purple",
"tags": ["overview"],
"description": "**Supabase PostgreSQL**\n\nURL: bfzizknbxbsfrffqityf.supabase.co\n\n**Existing Tables (migrated):**\n- person_details (8 rows)\n- deployments (45 rows)\n- devices (455 rows)\n- deployment_details (23 rows)\n\n**New Tables (to create):**\n- push_tokens\n- notification_settings\n- password_resets\n- chat_history\n\n**Updated:** Dec 18, 2025",
"x": 140,
"y": 80
},
{
"id": "table-person-details",
"type": "card",
"title": "person_details",
"subtitle": "Users & Authentication",
"borderColor": "blue",
"tags": ["existing", "auth"],
"description": "**Primary user table (auth)**\n\n```\nuser_id INTEGER PK (auto)\nuser_name TEXT (login)\nkey TEXT (password - PLAIN!)\nemail TEXT\nrole_ids TEXT (\"1,2\")\naccess_to_deployments TEXT (\"21,38,29\")\nfirst_name TEXT\nlast_name TEXT\naddress_street TEXT\naddress_city TEXT\naddress_zip TEXT\naddress_state TEXT\naddress_country TEXT\nphone_number TEXT\npicture TEXT (URL)\ntime_edit REAL\nuser_edit INTEGER\n```\n\n**Rows:** 8\n**Index:** email, user_name",
"x": 520,
"y": 80
},
{
"id": "warning-passwords",
"type": "card",
"title": "⚠️ SECURITY WARNING",
"borderColor": "red",
"tags": ["critical"],
"description": "**Passwords stored in PLAIN TEXT!**\n\nField `key` contains unencrypted passwords.\n\nExample: `key: \"anandk_8\"`\n\n**ACTION REQUIRED:**\n1. Add `password_hash` column\n2. Migrate existing passwords with bcrypt\n3. Remove `key` column\n4. Update auth.js to use bcrypt.compare()\n\n**Priority:** CRITICAL before production",
"x": 520,
"y": 340
},
{
"id": "table-deployments",
"type": "card",
"title": "deployments",
"subtitle": "Monitored Locations",
"borderColor": "green",
"tags": ["existing", "core"],
"description": "**Deployment = monitored home/location**\n\n```\ndeployment_id INTEGER PK (auto)\ntime_edit REAL (unix timestamp)\nuser_edit INTEGER (who edited)\ntime_zone_s TEXT (\"America/Los_Angeles\")\npersons INTEGER (people count)\ngender INTEGER (0-2)\nrace INTEGER\nborn INTEGER (year)\npets INTEGER\ncontext TEXT (notes about person)\nalarm_details TEXT (JSON with alarm config)\n```\n\n**Rows:** 45\n**Note:** `alarm_details` contains complex JSON",
"x": 900,
"y": 80
},
{
"id": "table-deployment-details",
"type": "card",
"title": "deployment_details",
"subtitle": "Extended Deployment Info",
"borderColor": "green",
"tags": ["existing", "core"],
"description": "**Additional deployment data**\n\n```\ndeployment_id INTEGER PK (FK)\nbeneficiary_id INTEGER (FK person)\ncaretaker_id INTEGER (FK person)\nowner_id INTEGER\ninstaller_id INTEGER\ndevices TEXT (JSON array of MACs)\naddress_street TEXT\naddress_city TEXT\naddress_zip TEXT\naddress_state TEXT\naddress_country TEXT\nwifis TEXT\nlat REAL\nlng REAL\ngps_age INTEGER\nnote TEXT\nfloor_plan TEXT (layout JSON)\noverlapps TEXT\n```\n\n**Rows:** 23",
"x": 900,
"y": 340
},
{
"id": "table-devices",
"type": "card",
"title": "devices",
"subtitle": "IoT Sensors",
"borderColor": "teal",
"tags": ["existing", "iot"],
"description": "**Physical sensor devices**\n\n```\ndevice_id INTEGER PK\ndevice_mac TEXT NOT NULL\nwell_id INTEGER\ndescription TEXT\nlocation INTEGER (room type)\nclose_to TEXT\nradar_threshold TEXT\nfw_version TEXT\nhw_version TEXT\nble_scan_period INTEGER\nble_scan_duration INTEGER\ntemperature_calib TEXT\nhumidity_calib TEXT\nreporting_period_s INTEGER\nreboot_time REAL\nled_schema TEXT\nalert_details TEXT\nother TEXT\ngroup_id INTEGER\n```\n\n**Rows:** 455\n**Unique:** (well_id, device_mac)",
"x": 1280,
"y": 80
},
{
"id": "table-disclaimers",
"type": "card",
"title": "disclaimers",
"subtitle": "User Agreements",
"borderColor": "gray",
"tags": ["existing"],
"description": "**Privacy policy agreements**\n\n```\nid INTEGER PK (auto)\nfirst_name TEXT\nlast_name TEXT\nuser_name TEXT\nemail TEXT\ndevices TEXT\ndate TIMESTAMPTZ\npolicy_version TEXT\n```",
"x": 1280,
"y": 340
},
{
"id": "new-tables-header",
"type": "card",
"title": "NEW TABLES (to create)",
"borderColor": "orange",
"tags": ["new"],
"description": "Tables needed for mobile app MVP.\n\nRequired for:\n- Push notifications\n- Password reset (Brevo)\n- Notification settings\n- Chat history persistence",
"x": 140,
"y": 500
},
{
"id": "table-push-tokens",
"type": "card",
"title": "push_tokens",
"subtitle": "NEW - Push Notification Tokens",
"borderColor": "orange",
"tags": ["new", "push"],
"description": "**Store device push tokens**\n\n```sql\nCREATE TABLE push_tokens (\n id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n user_id INTEGER REFERENCES person_details(user_id),\n token TEXT NOT NULL,\n platform TEXT CHECK (platform IN ('ios', 'android')),\n device_id TEXT,\n created_at TIMESTAMPTZ DEFAULT NOW(),\n updated_at TIMESTAMPTZ DEFAULT NOW(),\n UNIQUE(user_id, device_id)\n);\n```\n\n**Used by:** register_push_token endpoint",
"x": 520,
"y": 500
},
{
"id": "table-notification-settings",
"type": "card",
"title": "notification_settings",
"subtitle": "NEW - User Notification Preferences",
"borderColor": "orange",
"tags": ["new", "push"],
"description": "**Per-user notification settings**\n\n```sql\nCREATE TABLE notification_settings (\n user_id INTEGER PRIMARY KEY REFERENCES person_details(user_id),\n alerts_enabled BOOLEAN DEFAULT true,\n daily_report BOOLEAN DEFAULT true,\n quiet_hours_enabled BOOLEAN DEFAULT false,\n quiet_hours_start TIME DEFAULT '22:00',\n quiet_hours_end TIME DEFAULT '07:00',\n email_alerts BOOLEAN DEFAULT true,\n sms_alerts BOOLEAN DEFAULT false,\n updated_at TIMESTAMPTZ DEFAULT NOW()\n);\n```",
"x": 520,
"y": 700
},
{
"id": "table-password-resets",
"type": "card",
"title": "password_resets",
"subtitle": "NEW - Password Reset Tokens",
"borderColor": "orange",
"tags": ["new", "auth"],
"description": "**Forgot password flow (via Brevo)**\n\n```sql\nCREATE TABLE password_resets (\n id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n user_id INTEGER REFERENCES person_details(user_id),\n token TEXT NOT NULL UNIQUE,\n expires_at TIMESTAMPTZ NOT NULL,\n used_at TIMESTAMPTZ,\n created_at TIMESTAMPTZ DEFAULT NOW()\n);\n\nCREATE INDEX idx_password_resets_token \n ON password_resets(token);\nCREATE INDEX idx_password_resets_expires \n ON password_resets(expires_at);\n```\n\n**Flow:** User requests reset → token created → email via Brevo → user clicks link → token validated → password updated",
"x": 900,
"y": 500
},
{
"id": "table-chat-history",
"type": "card",
"title": "chat_history",
"subtitle": "NEW - AI Chat Messages",
"borderColor": "orange",
"tags": ["new", "chat"],
"description": "**Persist AI chat conversations**\n\n```sql\nCREATE TABLE chat_history (\n id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n user_id INTEGER REFERENCES person_details(user_id),\n deployment_id INTEGER REFERENCES deployments(deployment_id),\n role TEXT CHECK (role IN ('user', 'assistant')),\n content TEXT NOT NULL,\n created_at TIMESTAMPTZ DEFAULT NOW()\n);\n\nCREATE INDEX idx_chat_user_deployment \n ON chat_history(user_id, deployment_id);\n```\n\n**Note:** Optional for MVP, can add later",
"x": 900,
"y": 700
},
{
"id": "relationships",
"type": "card",
"title": "RELATIONSHIPS",
"borderColor": "purple",
"tags": ["overview"],
"description": "**Key Relationships:**\n\n```\nperson_details.access_to_deployments\n → deployments.deployment_id (comma-separated!)\n\ndeployment_details.deployment_id\n → deployments.deployment_id\n\ndeployment_details.beneficiary_id\n → person_details.user_id\n\ndeployment_details.caretaker_id\n → person_details.user_id\n\ndevices.well_id\n → deployments.deployment_id (via mapping)\n```\n\n**Note:** `access_to_deployments` is TEXT not FK!\nNeed to parse: `\"21,38,29\".split(',')`",
"x": 1280,
"y": 500
},
{
"id": "roles",
"type": "card",
"title": "ROLE SYSTEM",
"borderColor": "cyan",
"tags": ["auth"],
"description": "**role_ids field values:**\n\n```\n1 = Beneficiary (elderly person)\n2 = Caretaker (family member)\n3 = Admin\n4 = Installer\n```\n\n**Examples:**\n- `\"1\"` = only beneficiary\n- `\"1,2\"` = beneficiary + caretaker\n- `\"2\"` = only caretaker\n\n**In mobile app:**\n- Most users will be role 2 (caretakers)\n- They monitor role 1 (beneficiaries)",
"x": 1280,
"y": 700
},
{
"id": "migration-todo",
"type": "card",
"title": "MIGRATION TODO",
"borderColor": "red",
"tags": ["critical"],
"description": "**Before production:**\n\n1. ⬜ Add `password_hash` to person_details\n2. ⬜ Migrate passwords: bcrypt(key) → password_hash\n3. ⬜ Create push_tokens table\n4. ⬜ Create notification_settings table\n5. ⬜ Create password_resets table\n6. ⬜ (Optional) Create chat_history table\n7. ⬜ Add RLS policies for new tables\n8. ⬜ Remove `key` column after migration\n\n**SQL file:** /backend/migrations/001_add_auth_tables.sql",
"x": 140,
"y": 700
}
],
"connections": [
{"from": "header", "to": "table-person-details"},
{"from": "header", "to": "new-tables-header"},
{"from": "table-person-details", "to": "warning-passwords"},
{"from": "table-person-details", "to": "table-deployments", "label": "access_to_deployments"},
{"from": "table-deployments", "to": "table-deployment-details"},
{"from": "table-deployments", "to": "table-devices", "label": "well_id"},
{"from": "table-deployment-details", "to": "table-person-details", "label": "beneficiary_id"},
{"from": "new-tables-header", "to": "table-push-tokens"},
{"from": "new-tables-header", "to": "table-notification-settings"},
{"from": "new-tables-header", "to": "table-password-resets"},
{"from": "new-tables-header", "to": "table-chat-history"},
{"from": "new-tables-header", "to": "migration-todo"},
{"from": "table-push-tokens", "to": "table-person-details", "label": "FK user_id"},
{"from": "table-notification-settings", "to": "table-person-details", "label": "FK user_id"},
{"from": "table-password-resets", "to": "table-person-details", "label": "FK user_id"},
{"from": "table-chat-history", "to": "table-person-details", "label": "FK user_id"},
{"from": "table-chat-history", "to": "table-deployments", "label": "FK deployment_id"},
{"from": "table-devices", "to": "table-disclaimers"},
{"from": "table-disclaimers", "to": "relationships"},
{"from": "relationships", "to": "roles"}
],
"tagsDictionary": [
{"name": "overview", "color": "purple"},
{"name": "existing", "color": "green"},
{"name": "new", "color": "orange"},
{"name": "auth", "color": "blue"},
{"name": "core", "color": "green"},
{"name": "iot", "color": "teal"},
{"name": "push", "color": "pink"},
{"name": "chat", "color": "cyan"},
{"name": "critical", "color": "red"}
]
}