Reference implementation of an external Nomos provider for file system access.
This provider implements the Nomos Provider gRPC service contract to supply configuration data from local file system directories. It reads .csl files from a configured directory and makes them available to the Nomos compiler via gRPC.
- Directory-based access: Reads all
.cslfiles from a configured directory - gRPC interface: Implements
nomos.provider.v1.ProviderService - Multi-instance support: Work with multiple configuration directories simultaneously
- Atomic initialization: Automatic rollback if any instance fails to initialize
- Health checks: Built-in health monitoring
- Graceful shutdown: Clean resource cleanup on termination
New in v0.1.1: The file provider now supports multiple independent instances within a single service process. Each instance is identified by a unique alias and operates on its own directory.
- Independent Instances: Initialize multiple provider instances with different directories
- Isolated Operations: Each instance manages its own set of .csl files independently
- Atomic Guarantees: If any initialization fails, all instances are rolled back to ensure clean state
- Enhanced Errors: All error messages include the alias to identify which instance caused the error
# Define multiple provider instances
source:
alias: 'local'
type: 'file'
version: '0.1.1'
directory: './configs'
source:
alias: 'shared'
type: 'file'
version: '0.1.1'
directory: '/etc/shared-configs'
# Import from different instances
import:local:database # reads ./configs/database.csl
import:shared:network # reads /etc/shared-configs/network.cslWith multi-instance support, fetch paths follow this structure:
path[0]: alias # identifies the provider instance
path[1]: filename # base name without .csl extension
path[2+]: nested keys # optional: navigate within the file
Examples:
// Fetch entire file from "local" instance
path: ["local", "database"]
// Fetch nested key from "shared" instance
path: ["shared", "network", "ports", "http"]All errors include the alias for better debugging:
❌ provider instance "local" not found
❌ file "database" not found in provider instance "local"
❌ path element "host" not found in file "database" (provider instance "local")
The provider ensures atomic initialization:
source:
alias: 'instance1'
directory: './valid-path' # ✅ succeeds
source:
alias: 'instance2'
directory: './invalid-path' # ❌ fails
# Result: Both instances are rolled back
# Service returns to clean empty state
# Error message: "rolled back all 1 instance(s)"This prevents partial initialization states and ensures consistent behavior.
Declare the provider in your .csl file:
# Single instance (v0.1.0 compatible)
source:
alias: 'configs'
type: 'file'
version: '0.1.1'
directory: './configs'
import:configs:databaseRun nomos init to install the provider:
nomos initThen build your configuration:
nomos build -p ./config.cslThe provider can be run standalone for testing:
./nomos-provider-fileThe provider will:
- Start a gRPC server on a random available port
- Print
PROVIDER_PORT=<port>to stdout - Wait for RPC calls
The provider accepts the following configuration in the Init RPC call:
| Key | Type | Required | Description |
|---|---|---|---|
directory |
string | Yes | Absolute or relative path to directory containing .csl files |
- Go 1.25+ or later
- Protocol Buffers compiler (for regenerating proto stubs)
- Local clone of the Nomos repository (for now, until modules are published)
This provider currently uses replace directives in go.mod to reference the Nomos libraries locally. For production releases, these dependencies need to be published as proper Go modules or vendored into the repository.
make buildmake testgo run ./cmd/providerThis provider implements the nomos.provider.v1.ProviderService gRPC contract:
- Init: Initialize the provider with a directory path
- Fetch: Retrieve a
.cslfile by base name (without extension) - Info: Return provider metadata (alias, version, type)
- Health: Check provider health status
- Shutdown: Gracefully shut down the provider
Multi-Instance Format (v0.1.1+):
path: ["alias", "filename"] → fetches from specific instance
path: ["alias", "filename", "key"] → fetches nested key
path: ["local", "database"] → fetches ./configs/database.csl
path: ["shared", "network", "ports"] → fetches /etc/configs/network.csl -> ports
Wildcard Expansion (v0.1.1+):
path: ["alias", "filename", "*"] → returns the full object at that path (must be a map)
path: ["*"] → merges all files in the directory, returns full object
Single Instance Format (v0.1.0 compatible):
path: ["database"] → fetches database.csl
path: ["network"] → fetches network.csl
path: ["app", "config"] → fetches app.csl and navigates to config key
┌──────────────┐ gRPC ┌─────────────────┐
│ Nomos │ ──────────────────────▶ │ Provider │
│ Compiler │ Init/Fetch/Info/etc │ (subprocess) │
└──────────────┘ └─────────────────┘
│
▼
┌─────────────────┐
│ File System │
│ (.csl files) │
└─────────────────┘
The provider:
- Is started as a subprocess by the Nomos compiler
- Listens on a random TCP port
- Parses
.cslfiles from the configured directory - Returns structured data via gRPC
This project follows Semantic Versioning:
- MAJOR: Breaking changes to gRPC contract or behavior
- MINOR: New features, backward compatible
- PATCH: Bug fixes, backward compatible
See LICENSE file for details.
See CONTRIBUTING.md for contribution guidelines.