base implementation done, now onto mobile app

This commit is contained in:
user
2026-03-01 07:39:49 +02:00
parent 8197c775ba
commit eb2f82247b
9 changed files with 872 additions and 64 deletions

155
spec.mobile.md Normal file
View File

@@ -0,0 +1,155 @@
# 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`
Payload:
```json
{
"assets": [
{
"externalMediaId": "media-1",
"fileId": "01JNE3Q1S3KQX9Y7G2J8G7R0A8",
"mimeType": "image/jpeg",
"filename": "IMG_1234.jpg",
"capturedAt": "2026-03-01T10:05:00.000Z",
"sizeBytes": 1350021,
"hash": "sha256-...",
"metadata": {
"width": 3024,
"height": 4032
}
}
]
}
```
## 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:
- Dedup key: `(deviceId, externalMediaId)` when provided.
- `fileId` in `mobile_media_asset` is unique.
## 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.