WellNuo/docs/API_INTEGRATION_REQUEST.md
Sergei d453126c89 feat: Room location picker + robster credentials
- Backend: Update Legacy API credentials to robster/rob2
- Frontend: ROOM_LOCATIONS with icons and legacyCode mapping
- Device Settings: Modal picker for room selection
- api.ts: Bidirectional conversion (code ↔ name)
- Various UI/UX improvements across screens

PRD-DEPLOYMENT.md completed (Score: 9/10)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-24 15:22:40 -08:00

22 KiB

API Optimization Proposals for WellNuo Integration

Note: This document is for discussion purposes only, not final requirements. All proposals are open for discussion — we're happy to consider alternative approaches and adapt to your system's capabilities. Let's schedule a call to discuss the details if needed.


1. Introduction

1.1 Context

We're developing the WellNuo mobile application with our own database of users and beneficiaries. For working with IoT devices (sensors), we need integration with your Legacy API.

1.2 Current Integration Architecture

┌─────────────────┐      ┌──────────────────┐      ┌────────────────────┐
│  WellNuo App    │ ──▶  │  WellNuo Backend │ ──▶  │  eluxnetworks.net  │
│  (React Native) │      │  (Node.js)       │      │  Legacy API        │
└─────────────────┘      └──────────────────┘      └────────────────────┘
                                │
                                ▼
                         ┌──────────────┐
                         │  PostgreSQL  │
                         │  (WellNuo)   │
                         └──────────────┘

1.3 Summary of Request

The current API workflow requires creating a user in your database to obtain an authorization token. However:

  1. Users already exist in our DB — creating them in your DB is redundant
  2. We don't use these users — they're only needed to obtain a token
  3. This creates "garbage" records — unused accounts accumulate in your DB

Request: Add the ability for service integration via API Key without creating users.

1.4 Note on Current Capabilities

Technically, we can create users via the new_user_form endpoint:

POST /function/well-api/api
Content-Type: application/x-www-form-urlencoded

function=new_user_form
&firstName=John
&lastName=Doe
&email=john@example.com
&password=password123
&devices=[]
&agreementDate=2025-01-23
&privacyPolicyVersion=1.0
&phone=+1234567890

However, we consider this a legacy approach for the following reasons:

  1. Users aren't used as intended — we create them solely to obtain an authorization token, not for actual use in your system
  2. Data duplication — user information is stored in two databases without synchronization
  3. "Garbage" records — accounts accumulate in your DB that will never be used directly
  4. Password transmitted in plaintext — security issue (see section 2)

Proposal: Schedule a separate meeting to discuss and approve the integration architecture.

1.5 Which Endpoints We Actually Need

We NEED (minimum set):

Endpoint Purpose
set_deployment Create deployment and link devices to beneficiary
messages_age Sensor status: when last online (online/offline)
device_set_well_id Link device by well_id
device_form Configure sensor location (room)
device_list_by_deployment Get list of deployment's devices

We DON'T NEED:

Endpoint Why Not Needed
get_raw_data, get_presence_data Raw sensor data — processed on your side
dashboard_* Dashboard is shown through Julia AI
store_alarms, send_walarm Alarms are managed by your system
get_sensor_* Charts and analytics — not our task
request_node_red, store_flow We don't use Node-RED

Conclusion: We only need CRUD for deployments/devices and sensor status. All sensor data and analytics remain on your side.


2. Security Issues with Current API

2.1 Critical Issues

# Issue Severity Description
1 Password in request body 🔴 Critical credentials accepts ps (password) in POST body
2 Plaintext beneficiary password 🔴 Critical set_deployment requires beneficiary_password
3 No API Key auth 🟡 High No service authorization mechanism
4 Redundant user_name 🟡 Medium Every request requires user_name + token, even though token already identifies user

2.2 Issue #1 Details: Password in Request Body

Current request:

POST /function/well-api/api
Content-Type: application/x-www-form-urlencoded

function=credentials&user_name=anandk&ps=anandk_8&clientId=001&nonce=1234567890

Risks:

  • Password ends up in server access logs
  • Password may end up in proxy/WAF/CDN logs
  • When logging POST body — full credential compromise

2.3 Issue #2 Details: Plaintext Password When Creating Deployment

Current request:

POST /function/well-api/api
Content-Type: application/x-www-form-urlencoded

function=set_deployment
&user_name=anandk
&token=eyJ...
&deployment=NEW
&beneficiary_user_name=john_doe
&beneficiary_password=password123    ← PLAINTEXT PASSWORD
&beneficiary_email=john@example.com
...

Risks:

  • We're forced to know/generate user's password
  • Password transmitted in plain text
  • When logged — credential compromise

2.4 Issue #4 Details: Redundant user_name

Current request (any endpoint):

function=device_list
&user_name=anandk        ← why, if there's a token?
&token=eyJ...            ← token already contains user_id
&first=0
&last=100

Issue: If the JWT token already contains the user identifier, passing user_name is redundant.

Potential risk: Token confusion attack — using one user's token with another user's user_name. Server should verify the match, but this is an additional failure point.


3. Our Security Standard (WellNuo API)

For reference, here's how authorization works in our API:

3.1 Authorization via Bearer Token in Header

GET /api/auth/me
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json

3.2 Why This Is More Secure

Aspect Body (current) Header (proposed)
Logging Often logged Usually masked
Caching May be cached Not cached
CSRF protection Vulnerable Protected
Standard Non-standard RFC 6750

4. Requested Changes

4.1 Authorization Mechanism: Options

Requirement: Replace current flow with password in body with a more secure option.

Current flow (problematic):

1. POST credentials (user_name + password in body)  ← password in request body
2. Get JWT token (valid 7 days)
3. Use token + user_name in every request
4. Repeat steps 1-2 when token expires

Option A: API Key (static key)

1. You generate an API Key for our integration (once)
2. We use the key in header: Authorization: X-API-Key sk-wellnuo-xxx
3. When revocation needed — deactivate key and issue a new one

Pros: simplicity, no refresh logic, easy audit Cons: one key for entire integration

Option B: Service Account (token in header)

1. You create a service account for WellNuo (once)
2. We get token via credentials, but pass IT IN HEADER
3. Format: Authorization: Bearer eyJ...
4. user_name not needed in request body (token already identifies)

Pros: familiar JWT flow, can use existing infrastructure Cons: need refresh token

Main requirement (both options):

  • Token/key in header Authorization, not in body
  • Remove user_name from request body (redundant)

4.2 Endpoint: Authorization

CURRENT REQUEST

POST https://eluxnetworks.net/function/well-api/api
Content-Type: application/x-www-form-urlencoded

function=credentials
&user_name=anandk
&ps=anandk_8
&clientId=001
&nonce=1234567890

Response:

{
  "status": "200 OK",
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "expires_in": 604800
}

PROPOSED REQUEST

Option A: No longer needed (API Key doesn't require token request)

Option B: If key validation needed

POST https://eluxnetworks.net/function/well-api/api
Authorization: X-API-Key sk-wellnuo-xxxxxxxxxxxxxxxxxxxx
Content-Type: application/json

{
  "function": "validate_api_key"
}

Expected response:

{
  "status": "200 OK",
  "valid": true,
  "client_name": "WellNuo App",
  "permissions": ["deployments", "devices", "read_data"]
}

4.3 Endpoint: Create Deployment

CURRENT REQUEST

POST https://eluxnetworks.net/function/well-api/api
Content-Type: application/x-www-form-urlencoded

function=set_deployment
&user_name=anandk
&token=eyJ...
&deployment=NEW
&beneficiary_name=John Doe
&beneficiary_email=john@example.com
&beneficiary_user_name=john_doe        ← creates user in your DB
&beneficiary_password=password123      ← plaintext password
&beneficiary_address=123 Main St
&caretaker_username=jane_doe           ← creates another user
&caretaker_email=jane@example.com
&persons=1
&gender=Male
&race=0
&born=1955
&pets=0
&lat=40.7128
&lng=-74.0060
&wifis=["HomeWiFi|password123"]
&devices=[497,523]

Response:

{
  "status": "200 OK",
  "deployment_id": 42,
  "beneficiary_user_id": 156,
  "caretaker_user_id": 157
}

PROPOSED REQUEST

POST https://eluxnetworks.net/function/well-api/api
Authorization: Bearer eyJ... (or X-API-Key sk-wellnuo-xxx)
Content-Type: application/json

{
  "function": "set_deployment",
  "deployment": "NEW",
  "external_beneficiary_id": "clxyz123-uuid-from-our-db",
  "beneficiary_name": "John Doe",
  "beneficiary_email": "john@example.com",
  "devices": [497, 523]
}

Note: Only minimally required fields. Others (address, lat/lng, persons, pets, gender, born) — optional, we can pass them if needed.

Expected response:

{
  "status": "200 OK",
  "deployment_id": 42,
  "external_beneficiary_id": "clxyz123-uuid-from-our-db"
}

Key differences:

Aspect Current Proposed
Authorization token + user_name in body Token/key in header
User creation beneficiary_user_name + beneficiary_password NOT created
Beneficiary ID Generated in your DB external_beneficiary_id from our DB
Password Transmitted plaintext Not required

CURRENT REQUEST

POST https://eluxnetworks.net/function/well-api/api
Content-Type: application/x-www-form-urlencoded

function=device_set_well_id
&user_name=anandk
&token=eyJ...
&device_id=1234
&well_id=497
&mac=81A14C

Response:

{
  "status": "200 OK",
  "success": true
}

PROPOSED REQUEST

POST https://eluxnetworks.net/function/well-api/api
Authorization: Bearer eyJ... (or X-API-Key)
Content-Type: application/x-www-form-urlencoded

function=device_set_well_id
&device_id=1234
&well_id=497
&mac=81A14C

Change: Remove user_name and token from body, authorization via header.


4.5 Endpoint: Update Device Metadata

CURRENT REQUEST

POST https://eluxnetworks.net/function/well-api/api
Content-Type: application/x-www-form-urlencoded

function=device_form
&user_name=anandk
&token=eyJ...
&well_id=497
&device_mac=81A14C
&description=Living Room Sensor
&location=103

PROPOSED REQUEST

POST https://eluxnetworks.net/function/well-api/api
Authorization: Bearer eyJ... (or X-API-Key)
Content-Type: application/x-www-form-urlencoded

function=device_form
&well_id=497
&device_mac=81A14C
&description=Living Room Sensor
&location=103

Change: Remove user_name and token from body, authorization via header.


4.6 Endpoint: List Deployment Devices

CURRENT REQUEST

POST https://eluxnetworks.net/function/well-api/api
Content-Type: application/x-www-form-urlencoded

function=device_list_by_deployment
&user_name=anandk
&token=eyJ...
&deployment_id=42
&first=0
&last=100

PROPOSED REQUEST

POST https://eluxnetworks.net/function/well-api/api
Authorization: Bearer eyJ... (or X-API-Key)
Content-Type: application/x-www-form-urlencoded

function=device_list_by_deployment
&deployment_id=42
&first=0
&last=100

Change: Remove user_name and token from body, authorization via header.


4.7 Endpoint: Sensor Status (online/offline)

We need this endpoint — we show users when the sensor was last online.

CURRENT REQUEST

POST https://eluxnetworks.net/function/well-api/api
Content-Type: application/x-www-form-urlencoded

function=messages_age
&clientId=wellnuo_001
&user_name=anandk
&token=eyJ...
&nonce=12345
&macs=64B70888FAD4,64B708890F80,64B708890898

PROPOSED REQUEST

POST https://eluxnetworks.net/function/well-api/api
Authorization: Bearer eyJ... (or X-API-Key)
Content-Type: application/x-www-form-urlencoded

function=messages_age
&clientId=wellnuo_001
&nonce=12345
&macs=64B70888FAD4,64B708890F80,64B708890898

Change: Remove user_name and token from body, authorization via header.


5. Summary of Changes

5.1 Changes by Endpoint

Endpoint Current What to Remove What to Add
All endpoints user_name + token in body user_name, token from body Authorization header
set_deployment Creates user beneficiary_user_name, beneficiary_password external_beneficiary_id

5.2 List of Endpoints We Use

# Endpoint Purpose Change
1 credentials Get token Token in header (or API Key)
2 set_deployment Create deployment + external_beneficiary_id, no password
3 device_set_well_id Link device Auth in header
4 device_form Configure sensor (room) Auth in header
5 device_list_by_deployment List devices Auth in header
6 messages_age Sensor status (online/offline) Auth in header

5.3 Room Codes (location) — Reference

Code Name
102 Bedroom
103 Living Room
104 Kitchen
105 Bathroom
106 Hallway
107 Office
108 Garage
109 Dining Room
110 Basement
200 Other

6. Critical Bug: set_deployment Does Not Return deployment_id

6.1 Problem Description

When successfully creating a deployment via set_deployment, the API returns a minimal response without the created record's identifier.

Current response:

{"ok": 1, "status": "200 OK"}

Required response:

{"ok": 1, "deployment_id": 78, "status": "200 OK"}

6.2 Why This Is Critical for Integration

┌─────────────────────────────────────────────────────────────────────────────┐
│                         CURRENT FLOW (BROKEN)                               │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  1. WellNuo creates beneficiary in its DB                                   │
│     → beneficiary_id = "clxyz123-uuid"                                      │
│                                                                             │
│  2. WellNuo calls set_deployment in Legacy API                              │
│     → Deployment created successfully                                       │
│     → Response: {"ok": 1, "status": "200 OK"}                               │
│     → deployment_id = ???  ← UNKNOWN!                                       │
│                                                                             │
│  3. WellNuo CANNOT save the link:                                           │
│     beneficiary_deployments.legacy_deployment_id = NULL                     │
│                                                                             │
│  4. WellNuo CANNOT get sensors for this beneficiary:                        │
│     device_list_by_deployment requires deployment_id                        │
│     → INTEGRATION IMPOSSIBLE                                                │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

6.3 Workaround Attempts (unsuccessful)

We tried to find the created deployment through search:

# Attempt: find recently created deployments
curl -X POST "..." -d "function=find_deployments" -d "well_ids=70,71,72,73,74,75"

Why this doesn't work:

  • Race condition with parallel requests from different clients
  • IDs not guaranteed to be sequential
  • Requires additional API call
  • Unreliable in production environment

6.4 Working Request (for reproduction)

#!/bin/bash
TOKEN="<your_token>"
TS=$(date +%s)

curl -s -X POST "https://eluxnetworks.net/function/well-api/api" \
  -d "function=set_deployment" \
  -d "user_name=robster" \
  -d "token=$TOKEN" \
  -d "deployment=NEW" \
  -d "beneficiary_name=WellNuo Test" \
  -d "beneficiary_email=wellnuo-test-${TS}@wellnuo.app" \
  -d "beneficiary_user_name=wellnuo_test_${TS}" \
  -d "beneficiary_password=wellnuo123" \
  -d "beneficiary_address=WellNuo App" \
  -d "caretaker_username=anandk" \
  -d "caretaker_email=anandk@wellnuo.app" \
  -d "firstName=WellNuo" \
  -d "lastName=Test" \
  -d "persons=1" \
  -d "pets=0" \
  -d "gender=0" \
  -d "race=0" \
  -d "born=1960" \
  -d "lat=0" \
  -d "lng=0" \
  -d "wifis=[]" \
  -d "devices=[]"

# Response: {"ok": 1, "status": "200 OK"}
# Expected: {"ok": 1, "deployment_id": 78, "status": "200 OK"}

6.5 Required Fix

Modify the set_deployment function to return the created deployment ID:

{
  "ok": 1,
  "deployment_id": 78,
  "status": "200 OK"
}

Priority: 🔴 Blocker — integration is impossible without this fix.


7. Changes on WellNuo App Backend Side (what we plan to implement)

After agreeing on the new architecture, we plan to implement the following on the WellNuo App Backend side (the backend supporting the mobile application):

7.1 Planned Changes

# Change Description
1 API Proxy Layer All Legacy API calls go through WellNuo backend, not directly from mobile app
2 Secure Key Storage API Key stored in Doppler (secrets manager), not in code or .env files
3 Retry Logic Automatic retries for temporary errors (5xx, timeout)
4 Error Handling Graceful degradation — app works even if Legacy API is temporarily unavailable
5 Audit Logging Logging all Legacy API calls for debugging and monitoring

7.2 Architecture After Changes

┌─────────────────┐      ┌──────────────────┐      ┌────────────────────┐
│  WellNuo App    │      │  WellNuo Backend │      │  eluxnetworks.net  │
│  (React Native) │      │  (Node.js)       │      │  Legacy API        │
└────────┬────────┘      └────────┬─────────┘      └─────────┬──────────┘
         │                        │                          │
         │  1. Create beneficiary │                          │
         │ ───────────────────────▶                          │
         │                        │                          │
         │                        │  2. set_deployment       │
         │                        │  (API Key in header)     │
         │                        │ ─────────────────────────▶
         │                        │                          │
         │                        │  3. {deployment_id: 78}  │
         │                        │ ◀─────────────────────────
         │                        │                          │
         │                        │  4. Save mapping:        │
         │                        │  beneficiary_id ↔        │
         │                        │  deployment_id           │
         │                        │                          │
         │  5. Success            │                          │
         │ ◀───────────────────────                          │
         │                        │                          │

7.3 Mapping Table (WellNuo DB)

-- Link between WellNuo beneficiary and Legacy deployment
CREATE TABLE beneficiary_deployments (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    beneficiary_id UUID REFERENCES person_details(id),
    legacy_deployment_id INTEGER NOT NULL,  -- ID from eluxnetworks API
    created_at TIMESTAMP DEFAULT NOW(),
    UNIQUE(beneficiary_id)
);

8. Priorities

8.1 What's Needed for MVP (blockers)

# Requirement Priority Status
1 set_deployment returns deployment_id 🔴 Blocker Awaiting fix
2 API Key or Service Account authorization 🔴 Blocker Awaiting decision

8.2 What Can Be Done Later

# Requirement Priority
1 Remove user_name from body 🟡 Medium
2 Move token to header 🟡 Medium
3 external_beneficiary_id instead of creating users 🟢 Nice to have

If you have any questions or comments — let's schedule a call.