aviso-server 0.12.0

Notification service for data-driven workflows with live and replay APIs.
# Point-Cloud Filtering

Point-cloud streams let a provider publish many locations in one notification. A
subscriber supplies a polygon and receives the notification when any cloud point
lies inside the polygon or on its boundary.

Coordinates always use latitude first, then longitude. The canonical JSON forms
are:

- point: `[lat,lon]`
- polygon: `[[lat,lon],...]`, at least four pairs, first pair repeated last
- point cloud: `[[lat,lon],...]`, with at least one point

Point clouds accept JSON arrays only. Emitted CloudEvents always use arrays for
all spatial identifier values. See the
[alternative format](../schema-guide.md#alternative-coordinate-format) for
point and polygon strings.

## Schema

```yaml
notification_schema:
  observations:
    topic:
      base: observations
      key_order: [date]
    identifier:
      date:
        type: DateHandler
        canonical_format: "%Y%m%d"
        required: true
      point_cloud:
        type: PointCloudHandler
        required: true
        max_points: 10000
        description: >-
          Publishers provide point_cloud as [[latitude, longitude], ...].
          Watch and replay requests provide a closed polygon instead. The
          polygon satisfies this required field; subscribers must not send
          point_cloud.
    payload:
      required: true
```

The handler must use the reserved `point_cloud` key. A schema can contain only
one `PointCloudHandler`. The configured `max_points` defaults to 10,000 and
cannot exceed 10,000.

Do not put `point_cloud` in `topic.key_order`. Startup rejects that
configuration. Cloud coordinates stay in the `spatial_point_cloud` backend
metadata header. The subject contains only normal routing fields. Aviso also
stores a `spatial_bbox` header for coarse rejection before exact matching.

## Notify

The provider sends the cloud on `/notification`:

```bash
curl -sS -X POST "http://127.0.0.1:8000/api/v1/notification" \
  -H "Content-Type: application/json" \
  -d '{
    "event_type":"observations",
    "identifier":{
      "date":"20260826",
      "point_cloud":[
        [52.52,13.40],
        [48.14,11.58],
        [53.55,9.99]
      ]
    },
    "payload":{"source":"stations"}
  }'
```

Clouds do not need a closing repeat. Duplicate points are valid, and Aviso
preserves their order. Every latitude and longitude must be finite. Latitude
must be in `[-90, 90]`; longitude must be in `[-180, 180]`.

The canonical point-cloud JSON is limited to 60 KiB. This conservative Aviso
interoperability limit is informed by NATS-backed header transport and
near-limit round-trip tests. It leaves room for Aviso's other metadata, but is
not a protocol-wide NATS header limit. The point-count limit is checked first.

## Watch Or Replay

Subscribers use the reserved `polygon` query field. They do not send
`point_cloud`:

```bash
curl -N -X POST "http://127.0.0.1:8000/api/v1/replay" \
  -H "Content-Type: application/json" \
  -d '{
    "event_type":"observations",
    "identifier":{
      "date":"20260826",
      "polygon":[
        [52.40,13.20],
        [52.40,13.70],
        [52.70,13.70],
        [52.70,13.20],
        [52.40,13.20]
      ]
    },
    "from_id":"0"
  }'
```

The polygon satisfies a required `point_cloud` field for watch and replay. Aviso
first rejects non-overlapping bounding boxes. It then tests points in their
stored order and stops at the first match. Points on an edge or vertex match. A
cloud whose points are all outside does not match.

Requests are rejected when they send `point_cloud` to watch or replay, declare
`polygon` in a point-cloud schema, or combine incompatible spatial filters.

## CloudEvent Output

The event reconstructs the provider identifier as JSON:

```json
{
  "data": {
    "identifier": {
      "date": "20260826",
      "point_cloud": [
        [52.52, 13.4],
        [48.14, 11.58],
        [53.55, 9.99]
      ]
    }
  }
}
```

The request polygon is a filter. It is not substituted into the emitted
identifier.