From f425852ab727d06bcf8992d92b2ee1b2405e1cd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D7=A0=CF=85=CE=B1=CE=B7=20=D7=A0=CF=85=CE=B1=CE=B7=D1=95?= =?UTF-8?q?=CF=83=CE=B7?= Date: Wed, 18 Feb 2026 13:15:51 -0800 Subject: [PATCH] docs: Add configuration reference and fix config skeleton MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a dedicated configuration.md page documenting all osapi.yaml fields, environment variable overrides, and required fields. Fix the config skeleton in system-architecture.md to correctly nest url and bearer_token under api.client. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- ...2026-02-18-configuration-reference-docs.md | 39 +++ docs/docs/sidebar/configuration.md | 278 ++++++++++++++++++ docs/docs/sidebar/system-architecture.md | 10 +- 3 files changed, 323 insertions(+), 4 deletions(-) create mode 100644 .tasks/done/2026-02-18-configuration-reference-docs.md create mode 100644 docs/docs/sidebar/configuration.md diff --git a/.tasks/done/2026-02-18-configuration-reference-docs.md b/.tasks/done/2026-02-18-configuration-reference-docs.md new file mode 100644 index 00000000..5ef17881 --- /dev/null +++ b/.tasks/done/2026-02-18-configuration-reference-docs.md @@ -0,0 +1,39 @@ +--- +title: Add configuration reference documentation +status: done +created: 2026-02-18 +updated: 2026-02-18 +--- + +## Objective + +Document the `osapi.yaml` config file structure and `OSAPI_` environment +variable overrides. Users currently have no reference for available configuration +options outside of reading the Go source. + +## Scope + +- Document all config sections from `internal/config/types.go`: API (client, + server, security), NATS (server), Job (stream, consumer, KV, DLQ, client, + worker) +- Show example `osapi.yaml` with all fields and defaults +- Document the `OSAPI_` env var convention (`AutomaticEnv` + `SetEnvPrefix`) + with key mapping examples (dots become underscores, e.g., + `api.server.port` → `OSAPI_API_SERVER_PORT`) +- Note which fields are required vs optional and which are sensitive + (`signing_key`, `bearer_token`) + +## Notes + +- Viper config is in `cmd/root.go` (`initConfig`) +- Config types are in `internal/config/types.go` +- Validation is in `internal/config/schema.go` +- The `--osapi-file` / `-f` flag controls config file path (default `osapi.yaml`) + +## Outcome + +- Created `docs/docs/sidebar/configuration.md` with full annotated YAML + reference, env var mapping table, required fields, and per-section tables +- Fixed `system-architecture.md` config skeleton to nest `url` and + `bearer_token` under `api.client` instead of directly under `api` +- Added cross-link from system-architecture to the new configuration page diff --git a/docs/docs/sidebar/configuration.md b/docs/docs/sidebar/configuration.md new file mode 100644 index 00000000..d0e0c8eb --- /dev/null +++ b/docs/docs/sidebar/configuration.md @@ -0,0 +1,278 @@ +--- +sidebar_position: 3 +--- + +# Configuration + +OSAPI is configured through a YAML file and optional environment variable +overrides. + +## Config File + +By default OSAPI looks for `osapi.yaml` in the current working directory. +Override the path with the `-f` / `--osapi-file` flag: + +```bash +osapi --osapi-file /etc/osapi/osapi.yaml api server start +``` + +## Environment Variables + +Every config key can be overridden with an environment variable using the +`OSAPI_` prefix. Dots and nested keys become underscores, and the name is +uppercased: + +| Config Key | Environment Variable | +| ---------------------------------- | ---------------------------------------- | +| `debug` | `OSAPI_DEBUG` | +| `api.server.port` | `OSAPI_API_SERVER_PORT` | +| `api.server.security.signing_key` | `OSAPI_API_SERVER_SECURITY_SIGNING_KEY` | +| `api.client.security.bearer_token` | `OSAPI_API_CLIENT_SECURITY_BEARER_TOKEN` | +| `nats.server.host` | `OSAPI_NATS_SERVER_HOST` | +| `job.worker.hostname` | `OSAPI_JOB_WORKER_HOSTNAME` | + +Environment variables take precedence over file values. + +## Required Fields + +Two fields carry a `required` validation tag and must be set before the server +or client will start: + +| Key | Purpose | +| ---------------------------------- | ----------------------------- | +| `api.server.security.signing_key` | HS256 key for signing JWTs | +| `api.client.security.bearer_token` | JWT sent with client requests | + +Generate a signing key with `openssl rand -hex 32`. Generate a bearer token with +`osapi token generate`. + +## Full Reference + +Below is a complete `osapi.yaml` with every supported field and inline comments. +Values shown are representative defaults from the repository's config file. + +```yaml +# Enable verbose logging. +debug: true + +api: + client: + # Base URL the CLI client connects to. + url: 'http://0.0.0.0:8080' + security: + # JWT bearer token for client requests (REQUIRED). + # Generate with: osapi token generate + bearer_token: '' + + server: + # Port the REST API server listens on. + port: 8080 + security: + # HS256 signing key for JWT validation (REQUIRED). + # Generate with: openssl rand -hex 32 + signing_key: '' + cors: + # Origins allowed to make cross-origin requests. + # An empty list disables CORS headers entirely. + allow_origins: + - 'http://localhost:3001' + - 'https://osapi-io.github.io' + +nats: + server: + # Hostname the embedded NATS server binds to. + host: 'localhost' + # Port the embedded NATS server binds to. + port: 4222 + # Directory for JetStream file-based storage. + store_dir: '.nats/jetstream/' + +job: + # ── Shared infrastructure names ────────────────────────── + # JetStream stream name for job notifications. + stream_name: 'JOBS' + # Subject filter for the JOBS stream. + stream_subjects: 'jobs.>' + # KV bucket for immutable job definitions and status events. + kv_bucket: 'job-queue' + # KV bucket for worker result storage. + kv_response_bucket: 'job-responses' + # Durable consumer name. + consumer_name: 'jobs-worker' + + # ── Stream settings ───────────────────────────────────── + stream: + # Maximum age of messages in the stream (Go duration). + max_age: '24h' + # Maximum number of messages retained. + max_msgs: 10000 + # Storage backend: "file" or "memory". + storage: 'file' + # Number of stream replicas (1 for single-node). + replicas: 1 + # Discard policy when limits are reached: "old" or "new". + discard: 'old' + + # ── Consumer settings ─────────────────────────────────── + consumer: + # Maximum redelivery attempts before sending to DLQ. + max_deliver: 5 + # Time to wait for an ACK before redelivering. + ack_wait: '2m' + # Maximum outstanding unacknowledged messages. + max_ack_pending: 1000 + # Replay policy: "instant" or "original". + replay_policy: 'instant' + # Backoff durations between redelivery attempts. + back_off: + - '30s' + - '2m' + - '5m' + - '15m' + - '30m' + + # ── KV bucket settings ───────────────────────────────── + kv: + # TTL for KV entries (Go duration). + ttl: '1h' + # Maximum total size of the bucket in bytes. + max_bytes: 104857600 # 100 MiB + # Storage backend: "file" or "memory". + storage: 'file' + # Number of KV replicas. + replicas: 1 + + # ── Dead Letter Queue settings ────────────────────────── + dlq: + # Maximum age of messages in the DLQ. + max_age: '7d' + # Maximum number of messages retained. + max_msgs: 1000 + # Storage backend: "file" or "memory". + storage: 'file' + # Number of DLQ replicas. + replicas: 1 + + # ── Job client (CLI → NATS) ──────────────────────────── + client: + # NATS server hostname for the job client. + host: 'localhost' + # NATS server port for the job client. + port: 4222 + # Client name sent to NATS for identification. + client_name: 'osapi-jobs-cli' + + # ── Job worker ───────────────────────────────────────── + worker: + # NATS server hostname for the worker. + host: 'localhost' + # NATS server port for the worker. + port: 4222 + # Client name sent to NATS for identification. + client_name: 'osapi-job-worker' + # Queue group for load-balanced (_any) subscriptions. + queue_group: 'job-workers' + # Worker hostname for direct routing. Defaults to the + # system hostname when empty. + hostname: '' + # Maximum number of concurrent jobs to process. + max_jobs: 10 + # Key-value labels for label-based routing. + # Values can be hierarchical with dot separators. + # See Job System Architecture for details. + labels: + group: 'web.dev.us-east' +``` + +## Section Reference + +### `api.client` + +| Key | Type | Description | +| ----------------------- | ------ | ---------------------------------- | +| `url` | string | Base URL the CLI client targets | +| `security.bearer_token` | string | JWT for client auth (**required**) | + +### `api.server` + +| Key | Type | Description | +| ----------------------------- | -------- | ------------------------------------ | +| `port` | int | Port the API server listens on | +| `security.signing_key` | string | HS256 JWT signing key (**required**) | +| `security.cors.allow_origins` | []string | Allowed CORS origins | + +### `nats.server` + +| Key | Type | Description | +| ----------- | ------ | ------------------------------------ | +| `host` | string | Hostname the NATS server binds to | +| `port` | int | Port the NATS server binds to | +| `store_dir` | string | Directory for JetStream file storage | + +### `job` (top-level) + +| Key | Type | Description | +| -------------------- | ------ | ---------------------------------------- | +| `stream_name` | string | JetStream stream name | +| `stream_subjects` | string | Subject filter for the stream | +| `kv_bucket` | string | KV bucket for job definitions and events | +| `kv_response_bucket` | string | KV bucket for worker results | +| `consumer_name` | string | Durable consumer name | + +### `job.stream` + +| Key | Type | Description | +| ---------- | ------ | ---------------------------------- | +| `max_age` | string | Maximum message age (Go duration) | +| `max_msgs` | int | Maximum number of messages | +| `storage` | string | `"file"` or `"memory"` | +| `replicas` | int | Number of stream replicas | +| `discard` | string | Discard policy: `"old"` or `"new"` | + +### `job.consumer` + +| Key | Type | Description | +| ----------------- | -------- | -------------------------------------- | +| `max_deliver` | int | Max redelivery attempts before DLQ | +| `ack_wait` | string | ACK timeout (Go duration) | +| `max_ack_pending` | int | Max outstanding unacknowledged msgs | +| `replay_policy` | string | `"instant"` or `"original"` | +| `back_off` | []string | Backoff durations between redeliveries | + +### `job.kv` + +| Key | Type | Description | +| ----------- | ------ | -------------------------------- | +| `ttl` | string | Entry time-to-live (Go duration) | +| `max_bytes` | int | Maximum bucket size in bytes | +| `storage` | string | `"file"` or `"memory"` | +| `replicas` | int | Number of KV replicas | + +### `job.dlq` + +| Key | Type | Description | +| ---------- | ------ | --------------------------------- | +| `max_age` | string | Maximum message age (Go duration) | +| `max_msgs` | int | Maximum number of messages | +| `storage` | string | `"file"` or `"memory"` | +| `replicas` | int | Number of DLQ replicas | + +### `job.client` + +| Key | Type | Description | +| ------------- | ------ | ------------------------------- | +| `host` | string | NATS server hostname | +| `port` | int | NATS server port | +| `client_name` | string | NATS client identification name | + +### `job.worker` + +| Key | Type | Description | +| ------------- | ----------------- | ----------------------------------------- | +| `host` | string | NATS server hostname | +| `port` | int | NATS server port | +| `client_name` | string | NATS client identification name | +| `queue_group` | string | Queue group for load-balanced routing | +| `hostname` | string | Worker hostname (defaults to OS hostname) | +| `max_jobs` | int | Max concurrent jobs | +| `labels` | map[string]string | Key-value pairs for label-based routing | diff --git a/docs/docs/sidebar/system-architecture.md b/docs/docs/sidebar/system-architecture.md index f4cc7e48..eaf704b9 100644 --- a/docs/docs/sidebar/system-architecture.md +++ b/docs/docs/sidebar/system-architecture.md @@ -106,19 +106,21 @@ Configuration is managed by [Viper][] and loaded from an `osapi.yaml` file. Environment variables override file values using the `OSAPI_` prefix with underscore-separated keys (e.g., `OSAPI_API_SERVER_PORT`). -Minimal configuration skeleton: +Minimal configuration skeleton (see [Configuration](configuration.md) for the +full reference): ```yaml api: - url: 'http://localhost:8080' # Client target + client: + url: 'http://localhost:8080' + security: + bearer_token: '' server: port: 8080 security: signing_key: '' cors: allow_origins: [] - security: - bearer_token: '' nats: server: