# NODE.DC Gelios Gateway

Storage and read-model service for the Gelios provider domain. It has no
provider credential, no provider HTTP client, no scheduler and no command
transport.

## Boundary

The protected Engine L2 Gelios Collector is the only component that reaches
the provider and uses the Engine Credential. It submits authenticated unit
intake to this Gateway. The Gateway enforces the connection scope and approved
unit allowlist, persists current state/history, and exposes scoped read/SSE
contracts to other Engine workflows and map consumers.

Neither a provider token nor a credential reference is accepted, stored or
returned by this service.

## Runtime contracts

`GET /healthz` is unprotected and contains no secret material.

All `/internal/gelios/v1/*` routes require the internal service credential:

```text
Authorization: Bearer <NODEDC_INTERNAL_ACCESS_TOKEN>
X-NODEDC-Tenant-Id: <approved-tenant-id>
X-NODEDC-Connection-Id: <approved-connection-id>
```

```text
POST /internal/gelios/v1/intake/units
GET  /internal/gelios/v1/status
GET  /internal/gelios/v1/capabilities
GET  /internal/gelios/v1/units/current
GET  /internal/gelios/v1/stream
GET  /internal/gelios/v1/data-products/fleet.positions.current.v1/snapshot
GET  /internal/gelios/v1/data-products/fleet.positions.current.v1/stream
```

`intake/units` is disabled by default. It accepts a bounded payload with a
`units` array or an equivalent safe unit-list envelope; it does not accept a
URL, method, token or command. The command catalog remains visible only as
disabled ontology metadata.

The connection policy is explicit: `GELIOS_UNIT_SCOPE=allowlist` uses fixed
`GELIOS_ALLOWED_UNIT_IDS`; `GELIOS_UNIT_SCOPE=all` accepts every unit returned
by that already-approved tenant + connection, including units added later by
the provider. Missing units are never deleted from storage: their stable
provider IDs and last-seen history remain available to the presentation layer.

`fleet.positions.current.v1` is the first provider-neutral product. Its
snapshot and SSE patch stream contain semantic moving objects, position,
motion, quality and `active` / `stale` / `no-position` state. They deliberately
exclude raw telemetry and provider transport payloads. A consumer first fetches
the snapshot and then attaches the stream; the stream `ready` event never
pretends to be a complete current-state snapshot.

## Storage

The database requires TimescaleDB and PostGIS. It keeps a current projection,
append-only time-series snapshots, bounded restricted intake envelopes and
collection audit. Raw envelopes have no browser/API route and expire according
to `GELIOS_RAW_RETENTION_DAYS`.

## Local checks

```bash
npm ci
npm run smoke
```
