docs: DevOps documentation — complete docs/devops/ set
Adds the full devops-documentation OpenSpec change implementation. Separate from docs/developers/ — serves a different audience (operators, not API consumers). docs/devops/: - README.md — index and system overview - architecture.md — components, ports, data flow, Redis key patterns - environment-variables.md — all 7 env vars (required + optional, formats, .env example) - database.md — 4-table schema, indexes, constraints, migration runner - local-development.md — docker-compose setup, health checks, startup, Dockerfile gap noted - security.md — RSA key generation/rotation, CORS, bcrypt, secret storage guidance - operations.md — startup order, graceful shutdown, log reference, troubleshooting QA gates: 48/48 tasks complete. All env vars verified against source. All table names verified against migrations. All ports verified against docker-compose.yml. All internal links resolve. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
158
docs/devops/environment-variables.md
Normal file
158
docs/devops/environment-variables.md
Normal file
@@ -0,0 +1,158 @@
|
||||
# Environment Variables
|
||||
|
||||
Complete reference for all environment variables consumed by AgentIdP.
|
||||
|
||||
Variables are loaded from a `.env` file at startup via `dotenv`. In production, inject them directly into the process environment — do not commit `.env` to version control.
|
||||
|
||||
---
|
||||
|
||||
## Required Variables
|
||||
|
||||
These variables must be set. The server will throw and exit immediately if any are missing.
|
||||
|
||||
### `DATABASE_URL`
|
||||
|
||||
PostgreSQL connection string.
|
||||
|
||||
| | |
|
||||
|-|-|
|
||||
| **Required** | Yes |
|
||||
| **Format** | `postgresql://<user>:<password>@<host>:<port>/<database>` |
|
||||
| **Example** | `postgresql://sentryagent:sentryagent@localhost:5432/sentryagent_idp` |
|
||||
|
||||
The application uses `pg.Pool` with this connection string. Connection pool size uses the `pg` default (10 connections).
|
||||
|
||||
---
|
||||
|
||||
### `REDIS_URL`
|
||||
|
||||
Redis connection URL.
|
||||
|
||||
| | |
|
||||
|-|-|
|
||||
| **Required** | Yes |
|
||||
| **Format** | `redis://<host>:<port>` or `redis://<user>:<password>@<host>:<port>` |
|
||||
| **Example** | `redis://localhost:6379` |
|
||||
|
||||
Used for token revocation, rate limiting, and monthly token counters.
|
||||
|
||||
---
|
||||
|
||||
### `JWT_PRIVATE_KEY`
|
||||
|
||||
PEM-encoded RSA-2048 private key for signing JWT access tokens (RS256).
|
||||
|
||||
| | |
|
||||
|-|-|
|
||||
| **Required** | Yes |
|
||||
| **Format** | PEM string, including `-----BEGIN RSA PRIVATE KEY-----` header and footer |
|
||||
| **Example** | See [Security guide](security.md) for key generation |
|
||||
|
||||
In a `.env` file, use double quotes and encode newlines as `\n`:
|
||||
|
||||
```
|
||||
JWT_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nMIIEow...\n-----END RSA PRIVATE KEY-----"
|
||||
```
|
||||
|
||||
Alternatively, read from a file at startup (see [Security guide](security.md)).
|
||||
|
||||
---
|
||||
|
||||
### `JWT_PUBLIC_KEY`
|
||||
|
||||
PEM-encoded RSA-2048 public key for verifying JWT access tokens.
|
||||
|
||||
| | |
|
||||
|-|-|
|
||||
| **Required** | Yes |
|
||||
| **Format** | PEM string, including `-----BEGIN PUBLIC KEY-----` header and footer |
|
||||
| **Example** | Derived from `JWT_PRIVATE_KEY` — see [Security guide](security.md) |
|
||||
|
||||
Every authenticated request verifies the JWT signature using this key. If this key does not match the private key used to sign tokens, all authentication will fail.
|
||||
|
||||
---
|
||||
|
||||
## Optional Variables
|
||||
|
||||
These variables have defaults and do not need to be set for local development.
|
||||
|
||||
### `PORT`
|
||||
|
||||
HTTP port the Express server listens on.
|
||||
|
||||
| | |
|
||||
|-|-|
|
||||
| **Required** | No |
|
||||
| **Default** | `3000` |
|
||||
| **Format** | Integer |
|
||||
| **Example** | `PORT=8080` |
|
||||
|
||||
---
|
||||
|
||||
### `NODE_ENV`
|
||||
|
||||
Node.js environment flag.
|
||||
|
||||
| | |
|
||||
|-|-|
|
||||
| **Required** | No |
|
||||
| **Default** | `undefined` (treated as development) |
|
||||
| **Values** | `development`, `test`, `production` |
|
||||
| **Example** | `NODE_ENV=production` |
|
||||
|
||||
Effect: When `NODE_ENV=test`, HTTP request logging (Morgan) is disabled.
|
||||
|
||||
---
|
||||
|
||||
### `CORS_ORIGIN`
|
||||
|
||||
Allowed origin(s) for Cross-Origin Resource Sharing.
|
||||
|
||||
| | |
|
||||
|-|-|
|
||||
| **Required** | No |
|
||||
| **Default** | `*` (all origins) |
|
||||
| **Format** | URL string or `*` |
|
||||
| **Example** | `CORS_ORIGIN=https://app.mycompany.ai` |
|
||||
|
||||
In production, set this to the specific origin(s) that should be permitted to call the API. The default `*` is acceptable for a public API but restricts cookie-based auth flows (not applicable here — Bearer tokens only).
|
||||
|
||||
---
|
||||
|
||||
## Complete `.env` Example
|
||||
|
||||
```
|
||||
# Database
|
||||
DATABASE_URL=postgresql://sentryagent:sentryagent@localhost:5432/sentryagent_idp
|
||||
|
||||
# Redis
|
||||
REDIS_URL=redis://localhost:6379
|
||||
|
||||
# Application
|
||||
PORT=3000
|
||||
NODE_ENV=development
|
||||
CORS_ORIGIN=*
|
||||
|
||||
# JWT Keys (generate with openssl — see docs/devops/security.md)
|
||||
JWT_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEA...
|
||||
-----END RSA PRIVATE KEY-----"
|
||||
|
||||
JWT_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkq...
|
||||
-----END PUBLIC KEY-----"
|
||||
```
|
||||
|
||||
> Do not commit `.env` to version control. Add it to `.gitignore`.
|
||||
|
||||
---
|
||||
|
||||
## Variable Validation at Startup
|
||||
|
||||
The application validates required variables at startup in this order:
|
||||
|
||||
1. `JWT_PRIVATE_KEY` and `JWT_PUBLIC_KEY` — checked in `createApp()` before the server starts
|
||||
2. `DATABASE_URL` — checked when `getPool()` is first called (during `createApp()`)
|
||||
3. `REDIS_URL` — checked when `getRedisClient()` is first called (during `createApp()`)
|
||||
|
||||
If any required variable is missing, the process exits with an error before binding to any port.
|
||||
Reference in New Issue
Block a user