Files
illusory-mapp/spec.mobile.md

157 lines
3.1 KiB
Markdown

# Mobile Integration Spec (Stage 1)
## Base URL
- Processor endpoints are mounted under `/api/v1/mobile`.
## Headers
- Optional: `x-flow-id` for end-to-end trace correlation.
- Required for ping/sync endpoints: `x-device-id` with a previously registered `externalDeviceId`.
## Endpoints
### Register Device
- Method: `POST`
- Path: `/api/v1/mobile/register`
- Auth: none (trusted private network assumption)
Payload:
```json
{
"externalDeviceId": "android-1234",
"name": "Pixel 8 Pro",
"manufacturer": "Google",
"model": "Pixel 8 Pro",
"androidVersion": "15"
}
```
### Ping Device
- Method: `PUT`
- Path: `/api/v1/mobile/ping`
- Required header: `x-device-id`
Payload:
```json
{
"pingAt": "2026-03-01T10:15:00.000Z"
}
```
### Sync SMS
- Method: `PUT`
- Path: `/api/v1/mobile/sms/sync`
- Required header: `x-device-id`
Payload:
```json
{
"messages": [
{
"externalMessageId": "msg-1",
"sender": "+358401111111",
"recipient": "+358402222222",
"body": "Hello from device",
"sentAt": "2026-03-01T10:10:00.000Z",
"receivedAt": "2026-03-01T10:10:01.000Z",
"rawPayload": {
"threadId": "7"
}
}
]
}
```
### Sync Media Assets
- Method: `PUT`
- Path: `/api/v1/mobile/media/sync`
- Required header: `x-device-id`
- Content-Type: `multipart/form-data`
Upload contract:
- One request uploads one raw media file.
- Multipart field `file` is required (binary).
- Optional multipart metadata fields:
- `externalMediaId`
- `mimeType`
- `filename`
- `capturedAt` (ISO date string)
- `sizeBytes` (number)
- `hash`
- `metadata` (JSON object string)
- Optional metadata headers (alternative to multipart fields):
- `x-media-external-id`
- `x-media-mime-type`
- `x-media-filename`
- `x-media-captured-at`
- `x-media-size-bytes`
- `x-media-hash`
- `x-media-metadata` (JSON object string)
## Response Contract
Success:
```json
{
"data": {},
"error": null
}
```
Failure:
```json
{
"data": null,
"error": {
"flowId": "uuid",
"code": "VALIDATION_ERROR",
"message": "Human message",
"description": "Actionable description",
"detail": "Technical detail"
}
}
```
## Admin Query Contract
- Pagination:
- `page`: 1-based integer
- `pageSize`: integer
- Sorting:
- `sortBy`: operation-specific
- `sortOrder`: `asc` or `desc`
- Paginated response payload:
- `data`: rows
- `total`: full row count
- `page`, `pageSize`, `totalPages`
## Dedup Rules
- Device:
- Upsert on unique `externalDeviceId`.
- SMS:
- Dedup key #1: `(deviceId, externalMessageId)` when provided.
- Dedup key #2 fallback: `(deviceId, dedupHash)` where dedup hash is SHA-256 of `(deviceId + sentAt + sender + body)`.
- Media:
- Raw file is uploaded first and persisted in `file`.
- Then one `mobile_media_asset` row is created referencing uploaded `fileId`.
- Dedup key: `(deviceId, externalMediaId)` when provided.
## Operator Checklist
1. Register a device.
2. Send ping with `x-device-id` and verify dashboard `lastPingAt` updates.
3. Sync SMS and verify device detail `SMS` tab updates (polling every 5s).
4. Sync media and verify device detail `Media Assets` tab displays rows.