2025-06-24 19:56:56 +00:00
# Configuration Management
2025-09-09 19:34:03 +00:00
## Updated Configuration (September 2025)
The system has expanded configuration support for batch processing, enhanced observability, and Permit.io RBAC integration.
2025-06-24 19:56:56 +00:00
## Configuration Architecture
The system implements a hierarchical, environment-driven configuration system designed for flexibility, type safety, and testability. Configuration is managed through the `internal/serviceconfig` package with domain-specific sub-packages.
## Configuration Hierarchy
### Environment Variable Priority (First Wins)
1. **devbox.json "env" ** section - Highest priority for development
2. **devbox.json "init_hook" ** exports - Build-time configuration
3. * * .env file** variables - Local overrides
4. **System environment ** - Runtime environment variables
### Configuration Loading Process
``` go
// 1. Load .env file if present (development)
godotenv . Load ( )
// 2. Parse environment variables into struct
env . Parse ( & config )
// 3. Validate required fields
config . Validate ( )
// 4. Initialize dependent services
config . Initialize ( ctx )
```
## Base Configuration Structure
### Core Configuration (`serviceconfig/common.go`)
``` go
type BaseConfig struct {
// Application
LogLevel string ` env:"LOG_LEVEL" envDefault:"INFO" `
// Server
Port int ` env:"PORT" envDefault:"8080" `
HTTPHost string ` env:"HTTP_HOST" envDefault:"0.0.0.0" `
// Feature Flags
DisableAuth bool ` env:"DISABLE_AUTH" envDefault:"false" `
EnableOTEL bool ` env:"ENABLE_OTEL" envDefault:"false" `
// Observability
MetricsPath string ` env:"METRICS_PATH" envDefault:"/metrics" `
}
```
### Configuration Providers Pattern
``` go
// Interface composition for service dependencies
type ConfigProvider interface {
GetLogLevel ( ) string
GetPort ( ) int
GetHTTPHost ( ) string
IsAuthDisabled ( ) bool
}
// Service-specific configuration embeds base
type ServiceConfig struct {
BaseConfig
DatabaseConfig database . Config
AWSConfig aws . Config
QueueConfig queue . Config
}
```
## Domain-Specific Configuration
### Database Configuration (`serviceconfig/database/`)
``` go
type Config struct {
// Connection
Host string ` env:"PGHOST" envDefault:"localhost" `
Port int ` env:"PGPORT" envDefault:"5432" `
Database string ` env:"PGDATABASE" `
Username string ` env:"PGUSER" `
Password string ` env:"PGPASSWORD" `
// Connection Pool
MaxOpenConns int ` env:"DB_MAX_OPEN_CONNS" envDefault:"25" `
MaxIdleConns int ` env:"DB_MAX_IDLE_CONNS" envDefault:"25" `
ConnMaxLifetime int ` env:"DB_CONN_MAX_LIFETIME" envDefault:"300" `
// Security
SSLMode string ` env:"DB_SSL_MODE" envDefault:"require" `
NoSSL bool ` env:"DB_NOSSL" envDefault:"false" `
}
// Provider interface
type ConfigProvider interface {
GetDatabaseConfig ( ) Config
}
// Connection pool management
func ( c Config ) CreatePool ( ctx context . Context ) ( * pgxpool . Pool , error ) {
dsn := c . buildConnectionString ( )
return pgxpool . New ( ctx , dsn )
}
```
### AWS Configuration (`serviceconfig/aws/`)
``` go
type Config struct {
// Credentials
Region string ` env:"AWS_REGION" envDefault:"us-east-1" `
AccessKeyID string ` env:"AWS_ACCESS_KEY_ID" `
SecretAccessKey string ` env:"AWS_SECRET_ACCESS_KEY" `
SessionToken string ` env:"AWS_SESSION_TOKEN" `
Profile string ` env:"AWS_PROFILE" `
// Endpoints (for LocalStack/testing)
EndpointURL string ` env:"AWS_ENDPOINT_URL" `
S3UsePathStyle bool ` env:"AWS_S3_USE_PATH_STYLE" envDefault:"false" `
// Service-specific
S3Bucket string ` env:"S3_BUCKET" `
TextractRoleARN string ` env:"TEXTRACT_ROLE_ARN" `
}
// SDK integration
func ( c Config ) LoadAWSConfig ( ctx context . Context ) ( aws . Config , error ) {
var opts [ ] func ( * config . LoadOptions ) error
if c . Region != "" {
opts = append ( opts , config . WithRegion ( c . Region ) )
}
if c . EndpointURL != "" {
opts = append ( opts , config . WithEndpointResolverWithOptions (
aws . EndpointResolverWithOptionsFunc ( func ( service , region string , options ... interface { } ) ( aws . Endpoint , error ) {
return aws . Endpoint { URL : c . EndpointURL } , nil
} ) ,
) )
}
return config . LoadDefaultConfig ( ctx , opts ... )
}
```
### Queue Configuration (`serviceconfig/queue/`)
``` go
2025-09-09 19:34:03 +00:00
// Base queue configuration with batch processing support
2025-06-24 19:56:56 +00:00
type Config struct {
// Connection
QueueURL string ` env:"QUEUE_URL" `
MaxMessages int32 ` env:"QUEUE_MAX_MESSAGES" envDefault:"10" `
WaitTimeSeconds int32 ` env:"QUEUE_WAIT_TIME" envDefault:"20" `
VisibilityTimeout int32 ` env:"QUEUE_VISIBILITY_TIMEOUT" envDefault:"30" `
2025-09-09 19:34:03 +00:00
// Processing (enhanced for batch operations)
2025-06-24 19:56:56 +00:00
WorkerCount int ` env:"QUEUE_WORKER_COUNT" envDefault:"5" `
MaxRetries int ` env:"QUEUE_MAX_RETRIES" envDefault:"3" `
RetryDelay int ` env:"QUEUE_RETRY_DELAY" envDefault:"5" `
2025-09-09 19:34:03 +00:00
BatchSize int ` env:"QUEUE_BATCH_SIZE" envDefault:"10" `
2025-06-24 19:56:56 +00:00
}
// Service-specific queue configs
type DocumentInitConfig struct {
Config
DocumentSyncURL string ` env:"DOCUMENT_SYNC_URL" `
}
type QueryConfig struct {
Config
QuerySyncURL string ` env:"QUERY_SYNC_URL" `
}
```
### Authentication Configuration (`serviceconfig/auth/`)
``` go
type Config struct {
// Cognito Configuration
UserPoolID string ` env:"COGNITO_USER_POOL_ID" `
ClientID string ` env:"COGNITO_CLIENT_ID" `
ClientSecret string ` env:"COGNITO_CLIENT_SECRET" envSecret:"true" `
Domain string ` env:"COGNITO_DOMAIN" `
// URLs
RedirectURL string ` env:"COGNITO_REDIRECT_URL" `
LogoutURL string ` env:"COGNITO_LOGOUT_URL" `
// JWT Configuration
JWKSCacheExpiry time . Duration ` env:"JWKS_CACHE_EXPIRY" envDefault:"1h" `
TokenExpiry time . Duration ` env:"TOKEN_EXPIRY" envDefault:"24h" `
// Feature Flags
DisableAuth bool ` env:"DISABLE_AUTH" envDefault:"false" `
}
// Dynamic URL generation
func ( c Config ) GetAuthorizationURL ( ) string {
return fmt . Sprintf ( "https://%s.auth.%s.amazoncognito.com/oauth2/authorize" ,
c . Domain , extractRegion ( c . UserPoolID ) )
}
func ( c Config ) GetTokenURL ( ) string {
return fmt . Sprintf ( "https://%s.auth.%s.amazoncognito.com/oauth2/token" ,
c . Domain , extractRegion ( c . UserPoolID ) )
}
```
## Environment Variables Reference
### Core Application Variables
``` bash
# Logging and Debugging
LOG_LEVEL = DEBUG| INFO| WARN| ERROR # Default: INFO
ENABLE_OTEL = true| false # Default: false
# Server Configuration
PORT = 8080 # Default: 8080
HTTP_HOST = 0.0.0.0 # Default: 0.0.0.0
METRICS_PATH = /metrics # Default: /metrics
# Feature Flags
DISABLE_AUTH = true| false # Default: false (enable for local dev)
```
### Database Variables
``` bash
# Connection
PGHOST = localhost # Database host
PGPORT = 5432 # Database port
PGDATABASE = queryorchestration # Database name
PGUSER = postgres # Database user
PGPASSWORD = password # Database password
# Connection Pool
DB_MAX_OPEN_CONNS = 25 # Default: 25
DB_MAX_IDLE_CONNS = 25 # Default: 25
DB_CONN_MAX_LIFETIME = 300 # Seconds, Default: 300
# Security
DB_SSL_MODE = require| disable # Default: require
DB_NOSSL = true| false # Default: false (for local dev)
```
### AWS Configuration Variables
``` bash
# Credentials
AWS_REGION = us-east-1 # AWS region
AWS_ACCESS_KEY_ID = your-access-key # AWS access key
AWS_SECRET_ACCESS_KEY = your-secret # AWS secret key
AWS_SESSION_TOKEN = session-token # Optional session token
AWS_PROFILE = default # Optional AWS profile
# LocalStack/Testing
AWS_ENDPOINT_URL = http://localstack:4566 # Override AWS endpoints
AWS_S3_USE_PATH_STYLE = true| false # S3 path style (LocalStack)
# Service Configuration
S3_BUCKET = documents-bucket # S3 bucket for documents
TEXTRACT_ROLE_ARN = arn:aws:iam::... # Textract service role
```
### Queue Configuration Variables
``` bash
# Queue URLs (SQS)
STORE_EVENT_URL = https://sqs.region.amazonaws.com/account/store-events
DOCUMENT_INIT_URL = https://sqs.region.amazonaws.com/account/doc-init
DOCUMENT_SYNC_URL = https://sqs.region.amazonaws.com/account/doc-sync
DOCUMENT_CLEAN_URL = https://sqs.region.amazonaws.com/account/doc-clean
DOCUMENT_TEXT_URL = https://sqs.region.amazonaws.com/account/doc-text
QUERY_SYNC_URL = https://sqs.region.amazonaws.com/account/query-sync
QUERY_URL = https://sqs.region.amazonaws.com/account/query
CLIENT_SYNC_URL = https://sqs.region.amazonaws.com/account/client-sync
QUERY_VERSION_SYNC_URL = https://sqs.region.amazonaws.com/account/query-version-sync
# Queue Processing
QUEUE_MAX_MESSAGES = 10 # Messages per batch
QUEUE_WAIT_TIME = 20 # Long polling seconds
QUEUE_VISIBILITY_TIMEOUT = 30 # Message visibility
QUEUE_WORKER_COUNT = 5 # Concurrent workers
QUEUE_MAX_RETRIES = 3 # Retry attempts
QUEUE_RETRY_DELAY = 5 # Retry delay seconds
```
### Authentication Variables
``` bash
# AWS Cognito
COGNITO_USER_POOL_ID = us-east-1_xxxxxxx # Cognito User Pool ID
COGNITO_CLIENT_ID = client-id # Cognito App Client ID
COGNITO_CLIENT_SECRET = client-secret # Cognito App Client Secret
COGNITO_DOMAIN = your-domain # Cognito domain name
# URLs
COGNITO_REDIRECT_URL = http://localhost:8080/login-callback
COGNITO_LOGOUT_URL = http://localhost:8080/logout
# JWT Settings
JWKS_CACHE_EXPIRY = 1h # JWKS cache duration
TOKEN_EXPIRY = 24h # JWT token expiry
```
2025-12-16 04:26:06 +00:00
### Authorization Variables (Permit.io RBAC)
``` bash
# Permit.io API Configuration
PERMIT_IO_API_KEY = permit_key_xxxxxxx # Permit.io API key (project/env derived from key)
PERMIT_IO_TENANT = default # Permit.io tenant identifier (default: "default")
PERMIT_IO_PDP_URL = http://localhost:7766 # Policy Decision Point URL (optional, uses cloud if not set)
PERMIT_IO_BASE_URL = https://api.permit.io # Permit.io API base URL (optional, for testing)
```
**Note: ** The Permit.io project ID and environment ID are automatically derived from the API key
using the `/v2/api-key/scope` endpoint. Use a project-level or environment-level API key;
organization-level API keys are not supported.
2025-06-24 19:56:56 +00:00
## Configuration Validation
### Required Field Validation
``` go
type Config struct {
DatabaseURL string ` env:"DATABASE_URL,required" `
S3Bucket string ` env:"S3_BUCKET,required" `
QueueURL string ` env:"QUEUE_URL,required" `
}
// Validation on startup
func ( c * Config ) Validate ( ) error {
var errors [ ] string
if c . DatabaseURL == "" {
errors = append ( errors , "DATABASE_URL is required" )
}
if c . S3Bucket == "" {
errors = append ( errors , "S3_BUCKET is required" )
}
if len ( errors ) > 0 {
return fmt . Errorf ( "configuration validation failed: %s" , strings . Join ( errors , ", " ) )
}
return nil
}
```
### Secret Masking
``` go
// Automatic masking of sensitive values in logs
type Config struct {
DatabasePassword string ` env:"PGPASSWORD" envSecret:"true" `
AWSSecretKey string ` env:"AWS_SECRET_ACCESS_KEY" envSecret:"true" `
JWTSecret string ` env:"JWT_SECRET" envSecret:"true" `
}
// String() method automatically masks secrets
func ( c Config ) String ( ) string {
return env . String ( c ) // Automatically masks fields tagged with envSecret
}
```
## Development vs Production Configuration
### Development Environment (.env)
``` bash
# Local development overrides
LOG_LEVEL = DEBUG
DISABLE_AUTH = true
DB_NOSSL = true
AWS_ENDPOINT_URL = http://localstack:4566
AWS_S3_USE_PATH_STYLE = true
# Local service URLs
PGHOST = localhost
PGPORT = 5432
```
### Production Environment
``` bash
# Production settings
LOG_LEVEL = INFO
DISABLE_AUTH = false
DB_SSL_MODE = require
# Production AWS
AWS_REGION = us-east-1
# Credentials from IAM roles or environment
# Production database
PGHOST = production-db.region.rds.amazonaws.com
PGPORT = 5432
DB_SSL_MODE = require
```
### Testing Environment
``` bash
# Test-specific overrides
LOG_LEVEL = WARN
DISABLE_AUTH = true
DB_NOSSL = true
# Test containers
PGHOST = test-container
AWS_ENDPOINT_URL = http://test-localstack:4566
```
## Configuration Best Practices
### Security
- **Never commit secrets**: Use environment variables or secret management
- **Mask sensitive logs**: Use `envSecret` tag for automatic masking
- **Validate inputs**: Check configuration values at startup
- **Use least privilege**: Configure minimal required permissions
### Maintainability
- **Default values**: Provide sensible defaults for optional configuration
- **Documentation**: Document all environment variables and their purpose
- **Type safety**: Use strong typing and validation
- **Composition**: Build configuration from smaller, focused interfaces
### Testing
- **Override-friendly**: Allow easy configuration overrides for tests
- **Isolation**: Each test should have independent configuration
- **Realistic defaults**: Test configuration should mirror production patterns
- **Environment separation**: Clear separation between dev/test/prod configs