diff --git a/README.md b/README.md index d37bce9..42af424 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ This repository is documentation-only. It contains no runtime implementation cod | Device policy | [device-policy/v1.md](device-policy/v1.md) | Implemented baseline | | Offline Tier C tokens | [offline-tokens/v1.md](offline-tokens/v1.md) | Implemented baseline | | Runtime config surface | [runtime-config/v1.md](runtime-config/v1.md) | Implemented baseline | +| Gateway config surface | [gateway-config/v1.md](gateway-config/v1.md) | Implemented baseline | | Signing contract | [signing/v1.md](signing/v1.md) | Implemented baseline | ## Gaps diff --git a/gaps/open.md b/gaps/open.md index 5e3e79c..3e4507d 100644 --- a/gaps/open.md +++ b/gaps/open.md @@ -5,18 +5,11 @@ - Domain: `gateway-api/v1` - Status: Contract defined in `ori-gateway` (`internal/contracts/tier_c_enrichment.go`), DECISIONS.md entry recorded. MQTT topic constants and `app.go` handler are not yet wired. Runtime has no client for sending enrichment requests. - Summary: The advisory Tier C enrichment flow requires topic constants in `contracts.go` and a subscription handler in `app.go` on the gateway side, and a corresponding MQTT client on the runtime side. Until wired, enriched Tier C operator messages are unavailable. -- Tracking: `ori-platform/ori-gateway` — open issue for MQTT wiring. +- Tracking: `ori-platform/ori-gateway#41` ## G-16 — `reasoning_log` export missing from gateway runtimeclient - Domain: `gateway-api/v1` - Status: Export type documented in spec and served by runtime. Gateway `runtimeclient/mqtt.go` implements `Health`, `SensorHistory`, `ActionLog`, `TierCDecisionLog` but has no `ReasoningLog` method. - Summary: The reasoning audit export surface is unusable from the gateway until the runtimeclient method is added. -- Tracking: `ori-platform/ori-gateway` — open issue for runtimeclient gap. - -## G-17 — Gateway config surface not spec'd - -- Domain: (new) `gateway-config/v1` -- Status: `ori-gateway` has a working `gateway.yaml` config surface (`gateway.broker_url`, `gateway.heartbeat_interval_s`, `provider.*`, `reporting.*`, `sim.*`, `fleet.*`). No corresponding spec document exists. -- Summary: A `gateway-config/v1.md` spec is needed so the CLI, dashboard, and SDK can align with the gateway's configuration surface without reading Go source. -- Tracking: `ori-platform/ori-specs` — create `gateway-config/v1.md`. +- Tracking: `ori-platform/ori-gateway#42` diff --git a/gaps/resolved.md b/gaps/resolved.md index c9a2e95..80b6033 100644 --- a/gaps/resolved.md +++ b/gaps/resolved.md @@ -71,3 +71,11 @@ cross-sensor snapshot enrichment. Config lives under `reasoning.context_enricher default; fail-open. Staleness evaluated at prompt-build time, not event-emit time. Tier D never reaches the enricher by construction. See `ori-runtime/DECISIONS.md` 2026-06-08 entry and `docs/CAPABILITY_MATRIX.md` for full implementation scope. + +## G-17 — Gateway config surface not spec'd + +Resolved (2026-06-09): `gateway-config/v1.md` documents all `gateway.yaml` keys, +types, defaults, and validation rules for all five top-level sections: `gateway`, +`provider`, `reporting`, `sim`, `fleet`. Separation between `provider` (Tier 3 +reasoning) and `reporting.provider` (advisory/product) is made explicit. Tracked +by `ori-platform/ori-specs#5`. diff --git a/gateway-config/v1.md b/gateway-config/v1.md new file mode 100644 index 0000000..e525585 --- /dev/null +++ b/gateway-config/v1.md @@ -0,0 +1,194 @@ +# Gateway Config v1 + +> Status: Implemented in `ori-gateway` +> Source of truth: `internal/config/config.go`, `gateway.yaml.example` + +This document defines the `gateway.yaml` configuration surface for `ori-gateway`. +It covers all keys recognised by the config loader, their types, defaults, and +validation rules. The MQTT contract between runtime and gateway is in +[`gateway-api/v1.md`](../gateway-api/v1.md). + +--- + +## `gateway` + +Core LAN transport settings. + +| Key | Type | Default | Required | Notes | +|---|---|---|---|---| +| `broker_url` | `string` | — | Yes | MQTT broker URL, e.g. `tcp://localhost:1883` or `mqtts://broker:8883`. | +| `heartbeat_interval_s` | `int` | `30` | No | Must be positive. Gateway publishes `ori/gateway/health` on this interval. | + +--- + +## `provider` + +Tier 3 reasoning provider. This section is intentionally separate from +`reporting.provider`. `provider` routes runtime Tier 3 reasoning requests; +`reporting.provider` drives advisory/product features like weekly reports and +Tier C enrichment. Credentials from one must never flow into the other. + +| Key | Type | Default | Required | Notes | +|---|---|---|---|---| +| `name` | `string` | — | Yes | `echo \| llama_cpp \| cloud_llm` | +| `timeout_ms` | `int` | `10000` | No | Must be positive. Per-request provider timeout for Tier 3 reasoning. | + +### `provider.llama_cpp` + +Required when `provider.name: llama_cpp`. + +| Key | Type | Notes | +|---|---|---| +| `url` | `string` | Required. HTTP completion endpoint, e.g. `http://localhost:8080/completion`. | +| `model` | `string` | Fallback model name used when `/props` is unreachable or returns no model name. | + +### `provider.cloud_llm` + +Required when `provider.name: cloud_llm`. + +| Key | Type | Required | Notes | +|---|---|---|---| +| `vendor` | `string` | Yes | `claude \| openai \| gemini \| deepseek \| openai_compatible` | +| `api_key_env` | `string` | Yes | Name of an environment variable holding the API key. Must not contain whitespace. | +| `model` | `string` | Yes | Model identifier, e.g. `claude-sonnet-4-5`. | +| `base_url` | `string` | When `vendor: openai_compatible` | Custom base URL for OpenAI-compatible endpoints. | + +Cloud provider API keys are gateway-scoped environment variables. They must not +appear in runtime config (`ori.yaml`) or be carried inside MQTT reasoning envelopes. + +--- + +## `reporting` + +Advisory and product features: weekly site reports and Tier C enrichment. +All reporting features are disabled by default. `reporting.provider` must be +set whenever any reporting feature is enabled. + +`reporting` is intentionally a separate section from `provider`. Failures in the +reporting path must not affect Tier 3 reasoning, Tier C approval handling, Tier D +safety, or runtime fallback behaviour. + +| Key | Type | Default | Required | Notes | +|---|---|---|---|---| +| `provider` | `string` | `""` | When any feature enabled | `gemini` is the only supported value in v1. | + +### `reporting.gemini` + +Required when `reporting.provider: gemini` and any reporting feature is enabled. + +| Key | Type | Notes | +|---|---|---| +| `api_key_env` | `string` | Name of an environment variable holding the Gemini API key. Must not contain whitespace. | +| `model` | `string` | Gemini model identifier, e.g. `gemini-2.5-flash`. | + +### `reporting.weekly_report` + +Periodic site-level summary generation. + +| Key | Type | Default | Notes | +|---|---|---|---| +| `enabled` | `bool` | `false` | Enable weekly report generation. | +| `day` | `string` | — | Weekday name: `monday` through `sunday` (case-insensitive). Required when enabled. | +| `time` | `string` | — | 24-hour `HH:MM` format, e.g. `08:00`. Required when enabled. | +| `timezone` | `string` | — | IANA timezone string, e.g. `Africa/Lagos`. Required when enabled. Validated against the Go timezone database. | + +When `enabled: true`, `reporting.provider`, `day`, `time`, and `timezone` must all +be set. The gateway generates reports by consuming bounded runtime exports (via +the MQTT export surface defined in `gateway-api/v1.md`). It does not read runtime +SQLite directly. + +### `reporting.tier_c_enrichment` + +Advisory enrichment of Tier C operator messages. + +| Key | Type | Default | Notes | +|---|---|---|---| +| `enabled` | `bool` | `false` | Enable Tier C enrichment requests. When enabled, the gateway accepts enrichment requests from the runtime, enriches the operator message with advisory LLM context, and returns an advisory-only response. | + +Enrichment responses must not change action tier, proposed action, safe default, +approval requirement, or any other runtime authority field. Enrichment failure +must not delay or block the Tier C approval workflow. See `gateway-api/v1.md` for +the enrichment MQTT contract (gap G-15: transport wiring is pending). + +--- + +## `sim` + +SIM modem availability probe. Used by the heartbeat publisher to report +`sim_available` in the `ori/gateway/health` payload. + +| Key | Type | Default | Notes | +|---|---|---|---| +| `enabled` | `bool` | `false` | Enable SIM modem probe. | +| `modem_path` | `string` | — | Path to the modem device, e.g. `/dev/ttyUSB0`. Required when `enabled: true`. | + +--- + +## `fleet` + +> Status: Stub — deferred post-v1. + +Fleet coordination client. Currently an inert stub in `internal/fleet/fleet.go`. +Not wired in `app.go`. Config keys are validated but the module performs no +network operations until wiring is complete. + +| Key | Type | Default | Notes | +|---|---|---|---| +| `enabled` | `bool` | `false` | Enable fleet coordination. | +| `cloud_url` | `string` | — | Fleet cloud endpoint URL. Required when `enabled: true`. | + +--- + +## Annotated Example + +```yaml +gateway: + broker_url: "tcp://localhost:1883" + heartbeat_interval_s: 30 + +provider: + name: "echo" # echo | llama_cpp | cloud_llm + timeout_ms: 10000 + llama_cpp: + url: "http://localhost:8080/completion" + model: "llama-3.2-3b-instruct.gguf" # fallback if /props is unreachable + cloud_llm: + vendor: "claude" # claude | openai | gemini | deepseek | openai_compatible + api_key_env: "ANTHROPIC_API_KEY" + model: "claude-sonnet-4-5" + base_url: "" # required only for openai_compatible + +reporting: + provider: "gemini" + gemini: + api_key_env: "GEMINI_API_KEY" + model: "gemini-2.5-flash" + weekly_report: + enabled: false + day: monday + time: "08:00" + timezone: Africa/Lagos + tier_c_enrichment: + enabled: false + +sim: + enabled: false + modem_path: "/dev/ttyUSB0" + +fleet: + enabled: false + cloud_url: "" +``` + +--- + +## Key Separation Invariants + +- `provider` is for Tier 3 runtime reasoning requests only. Cloud reasoning + remains a gateway backend — the runtime never calls cloud APIs directly. +- `reporting` is for advisory/product features. Failures here must not affect + the reasoning path. +- API keys (`provider.cloud_llm.api_key_env`, `reporting.gemini.api_key_env`) + must be environment variable **names**, not values. Never commit key values. +- `reporting.*` credentials must not appear in `ori.yaml` (runtime config) and + must not be passed through MQTT reasoning envelopes.