{"id":43388866,"url":"https://github.com/autonomous-bits/nomos-provider-environment-variables","last_synced_at":"2026-02-17T23:14:49.367Z","repository":{"id":336019432,"uuid":"1147397869","full_name":"autonomous-bits/nomos-provider-environment-variables","owner":"autonomous-bits","description":null,"archived":false,"fork":false,"pushed_at":"2026-02-02T11:28:04.000Z","size":150,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-02T23:37:26.478Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/autonomous-bits.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-01T17:25:08.000Z","updated_at":"2026-02-02T11:27:41.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/autonomous-bits/nomos-provider-environment-variables","commit_stats":null,"previous_names":["autonomous-bits/nomos-provider-environment-variables"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/autonomous-bits/nomos-provider-environment-variables","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/autonomous-bits%2Fnomos-provider-environment-variables","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/autonomous-bits%2Fnomos-provider-environment-variables/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/autonomous-bits%2Fnomos-provider-environment-variables/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/autonomous-bits%2Fnomos-provider-environment-variables/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/autonomous-bits","download_url":"https://codeload.github.com/autonomous-bits/nomos-provider-environment-variables/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/autonomous-bits%2Fnomos-provider-environment-variables/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29561835,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-17T21:50:49.831Z","status":"ssl_error","status_checked_at":"2026-02-17T21:46:15.313Z","response_time":100,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-02-02T12:32:02.552Z","updated_at":"2026-02-17T23:14:49.362Z","avatar_url":"https://github.com/autonomous-bits.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Nomos Provider: Environment Variables\n\nA high-performance Nomos provider that enables configuration values to be pulled from environment variables.\n\n## Overview\n\nThe environment variables provider implements the Nomos `ProviderService` gRPC contract, running as a subprocess to fetch configuration values from the system environment. It supports:\n\n- **Direct variable access**: Fetch environment variables by name\n- **Hierarchical path mapping**: Transform paths like `[\"database\"][\"host\"]` to `DATABASE_HOST`\n- **Prefix filtering**: Scope to variables with a specific prefix (e.g., `MYAPP_`)\n- **Automatic type conversion**: Convert strings to numbers, booleans, and JSON objects\n- **Required variable validation**: Fail fast if critical variables are missing\n- **High performance**: Sub-millisecond fetch latency (57.6µs average)\n- **Thread-safe**: Handles 10,000+ concurrent requests safely\n\n## Features\n\n✨ **Key Features**:\n- Integrate with Twelve-Factor App methodology\n- Seamless Docker/Kubernetes integration\n- Cross-platform support (macOS, Linux, Windows)\n- Type-safe value conversion\n- Production-ready with \u003e80% test coverage\n- Zero data races (validated with Go race detector)\n\n## Installation\n\n### Option 1: Via Nomos CLI (Recommended)\n\nThe Nomos CLI automatically downloads the provider when it encounters a source declaration:\n\n```bash\n# The provider will be auto-downloaded on first use\nnomos build\n```\n\n### Option 2: Manual Download\n\nDownload the latest binary for your platform from [GitHub Releases](https://github.com/autonomous-bits/nomos-provider-environment-variables/releases):\n\n```bash\n# macOS (Apple Silicon)\ncurl -L -o nomos-provider-environment-variables \\\n  https://github.com/autonomous-bits/nomos-provider-environment-variables/releases/latest/download/nomos-provider-environment-variables-darwin-arm64\n\n# macOS (Intel)\ncurl -L -o nomos-provider-environment-variables \\\n  https://github.com/autonomous-bits/nomos-provider-environment-variables/releases/latest/download/nomos-provider-environment-variables-darwin-amd64\n\n# Linux (x86_64)\ncurl -L -o nomos-provider-environment-variables \\\n  https://github.com/autonomous-bits/nomos-provider-environment-variables/releases/latest/download/nomos-provider-environment-variables-linux-amd64\n\n# Linux (ARM64)\ncurl -L -o nomos-provider-environment-variables \\\n  https://github.com/autonomous-bits/nomos-provider-environment-variables/releases/latest/download/nomos-provider-environment-variables-linux-arm64\n\n# Windows (x86_64)\ncurl -L -o nomos-provider-environment-variables.exe \\\n  https://github.com/autonomous-bits/nomos-provider-environment-variables/releases/latest/download/nomos-provider-environment-variables-windows-amd64.exe\n\n# Make executable (Unix-like systems)\nchmod +x nomos-provider-environment-variables\n```\n\n### Option 3: From Source\n\nRequires Go 1.21 or later:\n\n```bash\ngit clone https://github.com/autonomous-bits/nomos-provider-environment-variables.git\ncd nomos-provider-environment-variables\nmake build\n```\n\n## Usage Examples\n\n### User Story 1: Basic Environment Variable Fetching\n\nInject runtime-specific configuration values without hardcoding them.\n\n**Environment Setup**:\n```bash\nexport DATABASE_URL=\"postgres://localhost:5432/mydb\"\nexport API_KEY=\"secret-key-12345\"\nexport DEBUG=\"true\"\n```\n\n**CSL Configuration**:\n```csl\nsource environment-variables as env {\n  version = \"1.0.0\"\n}\n\nconfig = {\n  database_url = import env[\"DATABASE_URL\"]\n  api_key = import env[\"API_KEY\"]\n  debug = import env[\"DEBUG\"]\n}\n```\n\n**Output** (types auto-converted):\n```json\n{\n  \"config\": {\n    \"database_url\": \"postgres://localhost:5432/mydb\",\n    \"api_key\": \"secret-key-12345\",\n    \"debug\": true\n  }\n}\n```\n\n---\n\n### User Story 2: Hierarchical Path Mapping\n\nOrganize configuration hierarchically in CSL while respecting flat environment variable conventions.\n\n**Environment Setup**:\n```bash\nexport DATABASE_HOST=\"localhost\"\nexport DATABASE_PORT=\"5432\"\nexport DATABASE_USER=\"admin\"\nexport REDIS_HOST=\"cache.example.com\"\n```\n\n**CSL Configuration**:\n```csl\nsource environment-variables as env {\n  version = \"1.0.0\"\n  config = {\n    separator = \"_\"\n    case_transform = \"upper\"\n  }\n}\n\n# Paths are transformed: [\"database\"][\"host\"] → DATABASE_HOST\ndatabase = {\n  host = import env[\"database\"][\"host\"]\n  port = import env[\"database\"][\"port\"]\n  user = import env[\"database\"][\"user\"]\n}\n\nredis = {\n  host = import env[\"redis\"][\"host\"]\n}\n```\n\n**Output**:\n```json\n{\n  \"database\": {\n    \"host\": \"localhost\",\n    \"port\": 5432,\n    \"user\": \"admin\"\n  },\n  \"redis\": {\n    \"host\": \"cache.example.com\"\n  }\n}\n```\n\n---\n\n### User Story 3: Prefix-Based Filtering\n\nScope the provider to specific namespaced variables for security and organization.\n\n**Environment Setup**:\n```bash\nexport MYAPP_DATABASE_URL=\"postgres://localhost\"\nexport MYAPP_API_KEY=\"secret123\"\nexport SYSTEM_PATH=\"/usr/bin\"  # Will not be accessible\n```\n\n**CSL Configuration**:\n```csl\nsource environment-variables as env {\n  version = \"1.0.0\"\n  config = {\n    prefix = \"MYAPP_\"\n    prefix_mode = \"prepend\"\n  }\n}\n\n# Prefix is automatically prepended\nconfig = {\n  database_url = import env[\"database\"][\"url\"]  # → MYAPP_DATABASE_URL\n  api_key = import env[\"api\"][\"key\"]            # → MYAPP_API_KEY\n}\n\n# This would fail: SYSTEM_PATH doesn't have MYAPP_ prefix\n# system_path = import env[\"SYSTEM_PATH\"]\n```\n\n**Benefits**: Prevents accidental access to system variables, provides namespace isolation.\n\n---\n\n### User Story 4: Type Conversion\n\nAutomatically convert string environment variables to appropriate types.\n\n**Environment Setup**:\n```bash\nexport PORT=\"8080\"\nexport ENABLE_DEBUG=\"true\"\nexport MAX_RETRIES=\"3\"\nexport TIMEOUT=\"30.5\"\nexport RETRY_CONFIG='{\"max_retries\":3,\"backoff_ms\":100}'\n```\n\n**CSL Configuration**:\n```csl\nsource environment-variables as env {\n  version = \"1.0.0\"\n  config = {\n    enable_type_conversion = true\n    enable_json_parsing = true\n  }\n}\n\nconfig = {\n  port = import env[\"PORT\"]                    # → 8080 (number)\n  debug = import env[\"ENABLE_DEBUG\"]           # → true (boolean)\n  max_retries = import env[\"MAX_RETRIES\"]      # → 3 (number)\n  timeout = import env[\"TIMEOUT\"]              # → 30.5 (float)\n  retry_config = import env[\"RETRY_CONFIG\"]    # → {max_retries: 3, backoff_ms: 100} (object)\n}\n```\n\n**Type Detection**:\n- Numbers: `\"123\"` → `123`, `\"3.14\"` → `3.14`\n- Booleans: `\"true\"`, `\"false\"`, `\"yes\"`, `\"no\"` (case-insensitive)\n- JSON: Values starting with `{` or `[` are parsed as structured data\n\n---\n\n### User Story 5: Required Variable Validation\n\nFail fast during initialization if critical environment variables are missing.\n\n**Environment Setup**:\n```bash\nexport API_KEY=\"secret123\"\n# DATABASE_URL is intentionally missing\n```\n\n**CSL Configuration**:\n```csl\nsource environment-variables as env {\n  version = \"1.0.0\"\n  config = {\n    required_variables = [\"API_KEY\", \"DATABASE_URL\", \"SECRET_KEY\"]\n  }\n}\n\nconfig = {\n  api_key = import env[\"API_KEY\"]\n}\n```\n\n**Result**: Provider initialization fails immediately with clear error:\n```\nError: Provider initialization failed\nrequired environment variables missing: DATABASE_URL, SECRET_KEY\n```\n\n**Benefits**: Catch configuration errors at compile-time instead of runtime.\n\n---\n\n## Configuration Reference\n\n### Complete Configuration Options\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `separator` | string | `\"_\"` | Character used to join path segments when resolving variable names |\n| `case_transform` | string | `\"upper\"` | Case conversion for variable names: `\"upper\"`, `\"lower\"`, or `\"preserve\"` |\n| `prefix` | string | `\"\"` | Prefix for filtering or prepending to variable names |\n| `prefix_mode` | string | `\"prepend\"` | Prefix behavior: `\"prepend\"` (auto-add prefix) or `\"filter_only\"` (explicit prefix required) |\n| `required_variables` | array | `[]` | List of environment variables that must exist at initialization |\n| `enable_type_conversion` | boolean | `true` | Automatically convert strings to numbers and booleans |\n| `enable_json_parsing` | boolean | `true` | Parse JSON-formatted string values into structured data |\n\n### Minimal Configuration\n\n```csl\nsource environment-variables as env {\n  version = \"1.0.0\"\n}\n```\n\nUses all default settings - suitable for most use cases.\n\n### Full Configuration Example\n\n```csl\nsource environment-variables as env {\n  version = \"1.0.0\"\n  config = {\n    separator = \"_\"\n    case_transform = \"upper\"\n    prefix = \"MYAPP_\"\n    prefix_mode = \"prepend\"\n    required_variables = [\"MYAPP_DATABASE_URL\", \"MYAPP_API_KEY\"]\n    enable_type_conversion = true\n    enable_json_parsing = true\n  }\n}\n```\n\n## Performance Characteristics\n\nBased on comprehensive benchmarks ([tests/integration/PERFORMANCE_BENCHMARKS.md](tests/integration/PERFORMANCE_BENCHMARKS.md)):\n\n| Metric | Performance | Success Criteria | Status |\n|--------|-------------|------------------|---------|\n| **Fetch Latency** | 57.6µs (0.0576ms) | \u003c10ms | ✅ **174x better** |\n| **Concurrent Throughput** | 78,931 ops/s | 10,000 concurrent requests | ✅ **Passed** |\n| **Data Race Safety** | Zero races detected | Zero races | ✅ **Validated** |\n| **Value Consistency** | 100% consistent | 100% consistent | ✅ **Passed** |\n\n**Hardware**: Apple M2, Go 1.22, macOS\n\n### Performance by Operation\n\n- String fetch: ~68µs\n- Number fetch: ~68µs\n- Boolean fetch: ~66µs\n- JSON parsing: ~72µs\n- Path resolution: ~64µs\n\nAll operations complete well under 10ms target.\n\n## Build Instructions\n\n### Prerequisites\n\n- Go 1.21 or later\n- make (optional, but recommended)\n- golangci-lint (for linting)\n\n### Basic Build\n\n```bash\n# Build for current platform\nmake build\n\n# Or use go directly\ngo build -o nomos-provider-environment-variables ./cmd/provider\n```\n\n### Development Workflow\n\n```bash\n# Run all checks (lint + test + build)\nmake dev\n\n# Individual commands\nmake lint           # Run linters\nmake test           # Run unit tests\nmake test-integration  # Run integration tests\nmake coverage       # Generate coverage report\n```\n\n### Cross-Platform Compilation\n\nBuild binaries for all supported platforms:\n\n```bash\nmake cross-compile\n```\n\nThis creates binaries in the `dist/` directory:\n- `nomos-provider-environment-variables-\u003cversion\u003e-darwin-amd64`\n- `nomos-provider-environment-variables-\u003cversion\u003e-darwin-arm64`\n- `nomos-provider-environment-variables-\u003cversion\u003e-linux-amd64`\n- `nomos-provider-environment-variables-\u003cversion\u003e-linux-arm64`\n- `nomos-provider-environment-variables-\u003cversion\u003e-windows-amd64.exe`\n\nSHA256 checksums are automatically generated in `dist/SHA256SUMS`.\n\n### Version Injection\n\nThe build automatically injects version information from Git tags:\n\n```bash\n# Build with version from git describe\nmake build\n\n# Or manually specify version\nVERSION=1.0.0 make build\n```\n\n## Testing\n\n### Run All Tests\n\n```bash\n# Unit tests with race detection\nmake test\n\n# Integration tests\nmake test-integration\n\n# All tests with coverage\nmake coverage\n```\n\n### Test Coverage\n\nCurrent coverage: **\u003e80%**\n\nView coverage report:\n```bash\nmake coverage\nopen coverage.html\n```\n\n### Performance Benchmarks\n\n```bash\n# Run fetch response time benchmarks\ngo test -tags=integration -bench=BenchmarkFetchResponseTime -benchmem ./tests/integration/\n\n# Run concurrent safety benchmarks\ngo test -tags=integration -bench=BenchmarkConcurrentFetches -benchmem ./tests/integration/\n\n# Validate zero data races (critical!)\ngo test -tags=integration -bench=BenchmarkConcurrentFetches_DataRaceValidation -race ./tests/integration/\n```\n\nSee [tests/integration/PERFORMANCE_BENCHMARKS.md](tests/integration/PERFORMANCE_BENCHMARKS.md) for detailed benchmark documentation.\n\n### Quickstart Validation\n\nValidate all examples from the quickstart guide:\n\n```bash\n./scripts/validate-quickstart.sh\n```\n\nThis script validates all usage patterns documented in the quickstart.\n\n## Troubleshooting\n\n### Error: \"environment variable not found\"\n\n**Symptom**:\n```\nError: environment variable not found: DATABASE_URL\n```\n\n**Cause**: The environment variable is not set in the current shell/environment.\n\n**Solution**:\n1. Verify the variable is set: `echo $DATABASE_URL`\n2. Set it if missing: `export DATABASE_URL=\"your-value\"`\n3. Check for typos in the variable name (case-sensitive on Unix/Linux)\n\n---\n\n### Error: \"required environment variables missing\"\n\n**Symptom**:\n```\nError: Provider initialization failed\nrequired environment variables missing: API_KEY, SECRET_KEY\n```\n\n**Cause**: One or more required variables (specified in `required_variables`) are not set.\n\n**Solution**:\n1. Set all required variables: `export API_KEY=\"...\" SECRET_KEY=\"...\"`\n2. Remove variables from `required_variables` if they're optional\n3. Check the exact variable names (including any prefix)\n\n---\n\n### Error: \"provider not found\"\n\n**Symptom**:\n```\nError: provider not found: environment-variables version 1.0.0\n```\n\n**Cause**: The provider binary is not installed or not in the expected location.\n\n**Solution**:\n1. The Nomos CLI should auto-download on first use\n2. Check installation: `ls .nomos/providers/environment-variables/1.0.0/`\n3. Manual installation: See \"Installation\" section above\n4. Verify binary has execute permissions: `chmod +x .nomos/providers/.../provider`\n\n---\n\n### Error: \"failed to parse JSON value\"\n\n**Symptom**:\n```\nError: failed to parse JSON value for CONFIG: invalid character '}' ...\n```\n\n**Cause**: The environment variable value starts with `{` or `[` but is malformed JSON.\n\n**Solution**:\n1. Fix the JSON syntax in the environment variable\n2. Escape special characters if needed\n3. Disable JSON parsing if you want the raw string:\n   ```csl\n   config = {\n     enable_json_parsing = false\n   }\n   ```\n\n---\n\n### Values are strings instead of numbers/booleans\n\n**Symptom**: `PORT=\"8080\"` is imported as string `\"8080\"` instead of number `8080`.\n\n**Cause**: Type conversion is disabled.\n\n**Solution**:\nEnable type conversion (it's on by default):\n```csl\nconfig = {\n  enable_type_conversion = true\n}\n```\n\n---\n\n### Case sensitivity issues on Windows vs Unix\n\n**Symptom**: Import works on Windows but fails on Linux (or vice versa).\n\n**Cause**: Environment variable names are case-sensitive on Unix/Linux but case-insensitive on Windows.\n\n**Solution**:\n- **Best practice**: Use uppercase variable names for cross-platform compatibility\n- On Unix: Ensure exact case match (`PATH` ≠ `path`)\n- On Windows: `PATH` and `path` refer to the same variable\n\n---\n\n### Provider hangs or doesn't respond\n\n**Symptom**: Provider starts but doesn't respond to gRPC requests.\n\n**Cause**: Port conflict or network configuration issue.\n\n**Solution**:\n1. Check provider startup output for `PROVIDER_PORT=\u003cport\u003e`\n2. Verify no other process is using that port: `lsof -i :\u003cport\u003e`\n3. Check firewall settings allow localhost gRPC connections\n\n---\n\n## Documentation\n\n- **[Quickstart Guide](specs/001-environment-variables/quickstart.md)** - 5-minute tutorial and common patterns\n- **[Specification](specs/001-environment-variables/spec.md)** - Feature requirements and user scenarios\n- **[Implementation Plan](specs/001-environment-variables/plan.md)** - Technical design and architecture\n- **[Performance Benchmarks](tests/integration/PERFORMANCE_BENCHMARKS.md)** - Detailed performance analysis\n- **[Provider Development Standards](docs/provider-development-standards.md)** - gRPC contract details\n\n## Contributing\n\nContributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for development guidelines.\n\n### Quick Start for Contributors\n\n```bash\n# Clone repository\ngit clone https://github.com/autonomous-bits/nomos-provider-environment-variables.git\ncd nomos-provider-environment-variables\n\n# Install development tools\nmake install-tools\n\n# Run development workflow\nmake dev\n\n# Submit PR with conventional commits\ngit commit -m \"feat: add new feature\"\n```\n\n## License\n\nSee [LICENSE](LICENSE) file for details.\n\n## Changelog\n\nSee [CHANGELOG.md](CHANGELOG.md) for version history following [Keep a Changelog](https://keepachangelog.com/) format.\n\n## Support\n\n- **Issues**: [GitHub Issues](https://github.com/autonomous-bits/nomos-provider-environment-variables/issues)\n- **Discussions**: [GitHub Discussions](https://github.com/autonomous-bits/nomos-provider-environment-variables/discussions)\n- **Security**: For security issues, see SECURITY.md","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fautonomous-bits%2Fnomos-provider-environment-variables","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fautonomous-bits%2Fnomos-provider-environment-variables","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fautonomous-bits%2Fnomos-provider-environment-variables/lists"}