Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
210 changes: 192 additions & 18 deletions gateway-api/v1.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,47 @@
# Gateway API v1

> Status: Design target (not yet implemented end-to-end in `ori-runtime`)
> Related open gaps: G-04, G-05
> Status: Runtime data exports implemented in `ori-runtime`; Tier 3 reasoning
> request/response remains a gateway milestone.
> Related open gaps: G-04, G-05, GW-020

This contract defines intended Tier 3 request/response integration between runtime and gateway.
This contract defines the MQTT boundary between `ori-runtime` and `ori-gateway`.
It covers two message families:

- Tier 3 reasoning request/response, used when runtime escalates reasoning to a LAN gateway.
- Runtime data export request/response, used by the gateway to generate reports and sync bounded runtime-owned data.

The gateway must not read runtime SQLite files directly. Runtime owns data semantics;
gateway owns product/reporting behavior.

## Transport

- Protocol: MQTT
- Broker: `gateway.broker_url`
- Pattern: request/response with correlation by `request_id`
- Runtime export responses are read-only, device-scoped, bounded, and paginated.
- HTTP export endpoints are not part of the runtime/gateway boundary.

## Topics

| Direction | Topic |
|---|---|
| Runtime -> Gateway | `ori/{device_id}/reasoning/request` |
| Gateway -> Runtime | `ori/{device_id}/reasoning/response` |
| Gateway heartbeat | `ori/gateway/health` |
| Message family | Direction | Topic |
|---|---|---|
| Reasoning | Runtime -> Gateway | `ori/{device_id}/reasoning/request` |
| Reasoning | Gateway -> Runtime | `ori/{device_id}/reasoning/response` |
| Gateway heartbeat | Gateway -> Runtime | `ori/gateway/health` |
| Runtime export | Gateway -> Runtime | `ori/{device_id}/export/request` |
| Runtime export | Runtime -> Gateway | `ori/{device_id}/export/response/{request_id}` |

Gateway subscribes to `ori/+/reasoning/request` to serve every runtime on the LAN.
The device owns the request/response namespace; the gateway owns only its health topic.
For runtime data exports, the gateway publishes a request to the target device's
export request topic and subscribes to `ori/+/export/response/+` or the specific
response topic for the request.

The device owns the `ori/{device_id}/...` namespace. The gateway owns only its
health topic.

## Request Payload
---

## Tier 3 Reasoning Request Payload

```json
{
Expand All @@ -42,7 +61,7 @@ The device owns the request/response namespace; the gateway owns only its health
}
```

## Response Payload
## Tier 3 Reasoning Response Payload

```json
{
Expand All @@ -58,7 +77,9 @@ The device owns the request/response namespace; the gateway owns only its health
}
```

`request_id` must match a pending runtime request. On provider timeout or failure, the gateway still publishes an error response with the original `request_id` and an `error` string so the runtime does not wait for an unanswered request.
`request_id` must match a pending runtime request. On provider timeout or failure,
the gateway still publishes an error response with the original `request_id` and
an `error` string so the runtime does not wait for an unanswered request.

## Heartbeat Payload

Expand All @@ -68,31 +89,184 @@ Published on `ori/gateway/health` every 30 seconds by default.
{
"status": "starting|healthy|degraded",
"uptime_s": 12.5,
"provider": "echo|llama_cpp|claude",
"provider": "echo|llama_cpp|claude|other",
"sim_available": false,
"timestamp_ms": 0
}
```

`uptime_s` is a floating-point number of seconds to match runtime health semantics.

## Timeout and Retry (Target Behavior)
## Tier 3 Timeout and Retry Target Behavior

| Parameter | Target |
|---|---|
| response timeout | 10s default |
| retry | 1 retry |
| fallback | local Tier 2 (`local_slm`) on timeout/unreachable |

## Availability Check
## Gateway Availability Check

Target behavior:

- runtime subscribes to `ori/gateway/health`
- gateway publishes heartbeat every 30s
- runtime marks gateway unavailable after heartbeat silence window

Current runtime note:
---

## Runtime Export Request Payload

Published by gateway to `ori/{device_id}/export/request`.

```json
{
"request_id": "uuid4-string",
"export_type": "sensor_history",
"device_id": "site-a-edge-01",
"since_ms": 1717000000000,
"until_ms": 1717600000000,
"limit": 500,
"page_token": "",
"params": {
"sensor_id": "current-main",
"bucket_ms": 3600000
}
}
```

### Request Fields

| Field | Required | Notes |
|---|---:|---|
| `request_id` | yes | Correlates request and response. Must be non-empty. |
| `export_type` | yes | One of `health`, `sensor_history`, `action_log`, `tier_c_decision_log`. |
| `device_id` | yes | Must match the target runtime device ID. |
| `since_ms` | export-specific | Unix milliseconds lower bound. Required for `sensor_history`. |
| `until_ms` | export-specific | Unix milliseconds upper bound. Required for `sensor_history`. |
| `limit` | no | Runtime caps page size. Clients should use `<= 1000`. |
| `page_token` | no | Empty string for first page. Subsequent value comes from response `next_page_token`. |
| `params` | no | Export-specific object. Defaults to `{}`. |

`until_ms` must be greater than or equal to `since_ms` when both are present.
Invalid or mismatched requests return an error response envelope instead of
raising transport-level failures.

## Runtime Export Response Payload

Published by runtime to `ori/{device_id}/export/response/{request_id}`.

```json
{
"request_id": "uuid4-string",
"export_type": "sensor_history",
"device_id": "site-a-edge-01",
"items": [],
"next_page_token": "",
"complete": true,
"error": null
}
```

Every response, including validation failures, includes the envelope fields above.
When `error` is non-null, `items` is empty and `complete` is true.

## Supported Export Types

### `health`

Returns a single runtime health snapshot in `items[0]`. The snapshot is the same
runtime-owned diagnostic shape used by local health consumers and includes device
identity, uptime, capability posture, sensor status, alert timestamps,
DevicePolicy state, and advisory remote-command lockout state when available.

Request notes:

- `since_ms`, `until_ms`, and `params` are ignored.

### `sensor_history`

Returns bounded sensor history for one sensor.

Request `params`:

| Field | Required | Notes |
|---|---:|---|
| `sensor_id` | yes | Runtime sensor ID to export. |
| `bucket_ms` | no | Aggregation bucket width in milliseconds. `3600000` means hourly buckets. `0` or omitted returns runtime-selected source rows. |

Response item shape for unbucketed rows:

```json
{
"sensor_id": "current-main",
"sensor_type": "current_clamp",
"timestamp": 1717000000000,
"value": 4.2,
"unit": "ampere",
"quality": 0.99,
"sample_count": 1,
"tier": "raw|5min|hourly|daily"
}
```

Response item shape for bucketed rows:

```json
{
"sensor_id": "current-main",
"sensor_type": "current_clamp",
"timestamp": 1717000000000,
"start_ms": 1717000000000,
"end_ms": 1717003600000,
"value": 4.2,
"avg_value": 4.2,
"min_value": 3.8,
"max_value": 4.8,
"unit": "ampere",
"quality": null,
"sample_count": 12,
"bucket_ms": 3600000,
"tier": "bucketed"
}
```

Bucket averages are weighted by `sample_count` so compacted runtime rows remain
statistically meaningful when re-aggregated for weekly reports.

### `action_log`

Returns bounded action-log rows for the runtime device.

Optional request `params`:

| Field | Required | Notes |
|---|---:|---|
| `tier` | no | Optional `A`, `B`, `C`, or `D` filter. |

Response items include action name, tier, execution status, approval status,
action taken, operator response, proposal ID, safe-default usage, device ID,
sensor ID, sensor type, trigger name, and timestamp.

### `tier_c_decision_log`

Returns bounded Tier C proposal/decision rows for the runtime device.

Response items include dataset-ready Tier C context: device ID, site type,
location, timezone, sensor reading, bounded history window, skill name, trigger
name, proposed action, confidence, reasoning tier/model, prompt summary, operator
decision, decision latency, safe-default usage, final action result, later
outcome, proposal ID, and creation timestamp.

## Runtime Export Invariants

- runtime currently uses internet reachability probe in tier selection path
- broker-heartbeat based availability is pending gateway milestone work
- Runtime export requests are read-only. They must never mutate state, change
policy, trigger actions, or affect Tier C/Tier D paths.
- Runtime owns data semantics. Gateway must not infer runtime SQLite table names
or read runtime database files directly.
- Export responses must be bounded and paginated.
- Requests must be scoped to the target `device_id`.
- Runtime must return error envelopes for malformed requests rather than leaving
request/response calls unanswered.
- Cloud/provider SDKs do not belong in the runtime export implementation.
Gateway/product layers own reporting providers.
Loading