Rules Configuration
rules.svc reads one bootstrap YAML file at start, overlays it with command-line flags, then merges
the result over the service node it resolves from the config plane. This page enumerates every key
the binary actually reads. Keys not listed here are not read by this service.
For what the service does with that configuration once it is up, see Service. For diagnosing a boot that produced no output, see Troubleshooting.
Where configuration comes from
Section titled “Where configuration comes from”| Source | Sets | Precedence |
|---|---|---|
Config plane (config.url / config.path) | The resolved service node fetched at boot | Lowest. The bootstrap map is merged over it |
| Bootstrap YAML file | Every key on this page | Beats the config plane |
| Command-line flags | The fourteen flags below | Highest. A non-empty flag overwrites the YAML value |
| Tenant config, per tenant | meta.url, meta.localdir, meta.isexternal, timeouts.services | Read from the tenant record on every tenant refresh |
The bootstrap file defaults to .rules.yaml in the working directory. Change it with -f.
rules.svc -f /etc/kis/rules.yamlAn empty flag falls back to the YAML value; a non-empty flag is written back into the bootstrap map
and wins. At boot the resolved config-plane node is fetched first and the bootstrap map is merged on
top of it, so a key present in the bootstrap file always beats the same key published by the config
plane. That includes port, which is re-read from the merged map immediately before the listener is
created.
Command-line flags
Section titled “Command-line flags”These fourteen persistent flags and the version subcommand are everything the service declares.
The command framework adds its own help and completion commands on top.
| Flag | Type | Default | Effect |
|---|---|---|---|
-f, --config | string | .rules.yaml | Bootstrap YAML file path |
-p, --port | string | none | HTTP listen port |
--sid | string | none | Service instance id |
--datacenter | string | none | Datacenter label |
--cluster | string | none | Cluster label |
--config_url | string | none | Config server URL |
--config_apikey | string | none | Config server API key. Boot fails with error: either config.apikey or svccert should be present when config.url is set and neither is |
--servicediscovery_url | string | none | Service registry URL |
--servicediscovery_apikey | string | none | Service registry API key. Boot fails with error: either servicediscovery_apikey or svccert should be present when servicediscovery_url is set and neither is |
--svccert | string | none | Service certificate path |
--svckey | string | none | Service private key path |
--rootcacert | string | none | Root CA certificate path |
--jwt_public_key | string | none | Public key for verifying tenant tokens |
--zerotrust | string | none: resolves to true | true (case-insensitive) serves over TLS; any other non-empty value is false, including yes and 1 |
There is no --host, no --log-level and no --jwt_private_key flag, those are configuration keys
only. rules.svc version prints the service name, version, commit hash, build timestamp and the
build’s age. The build number is compiled in but never printed.
Listener
Section titled “Listener”| Key | Type | Default | Effect |
|---|---|---|---|
port | string | none: required | TCP port the HTTP server binds. Boot aborts with invalid/empty port provided when neither the flag nor this key is set. |
host | string | "" (all interfaces) | Bind address, joined as host:port. |
reuseport | bool | true | Bind with SO_REUSEPORT so several instances share the port. Set false for a plain listener. |
TLS and identity
Section titled “TLS and identity”| Key | Type | Default | Effect |
|---|---|---|---|
zerotrust | bool | true | When true the server is served over TLS with the configured service certificate. When false the listener binds plain HTTP and needs no certificate. |
svccert | string (path) | "" | Service certificate, PEM. |
svckey | string (path) | "" | Service private key, PEM. |
rootcacert | string (path) | "" | Root CA used to validate peers. |
rootcakey | string (path) | "" | Root CA key, used by certificate auto-renewal. No flag. |
insecureskipverify | bool | false | Disables peer certificate verification. |
auto_renew_certificates | bool | true | Enables automatic certificate renewal. |
jwt_public_key | string (path) | "" | Public key for verifying tenant tokens on /rule. |
jwt_private_key | string (path) | "" | Private key for signing tokens. Configuration only. This binary registers no flag for it. |
With zerotrust: true the service does not start without both svccert and svckey: startup
resolves a TLS entry named http and exits 1 with tlsconfig not found for http when it is absent.
Config plane
Section titled “Config plane”| Key | Type | Default | Effect |
|---|---|---|---|
config.url | string (URL) | "" | Remote config server. Wins over config.path when both are set; config.path is then logged as ignored. |
config.path | string (path) | "" | Local directory of config documents. |
config.apikey | string | "" | API key for the remote config server. |
config.cache | string (path) | "" | Warm-cache file holding the last-known-good config, read when the remote is down. Remote mode only. |
boot.retry_window | duration string or int seconds | 90s | How long boot keeps retrying the service-discovery and config clients before giving up. Retries back off from 1s to a 10s ceiling. Raise it when the config plane starts after this service. |
With neither config.url nor config.path set, the bootstrap file itself is the config source. A
config client that cannot be built inside the retry window fails boot with config-client-init and
exit 1.
Rule source
Section titled “Rule source”Rule sets are files in each tenant’s product, its rules/ folder: one folder per rule set, named for
it, holding the set’s .grl files and vocabulary files. See
Service for the
layout and how a change reaches the service.
The product is read through the tenant’s meta source, set in the tenant’s configuration:
| Key | Type | Default | Effect |
|---|---|---|---|
meta.url | string (URL) | "" | Meta server serving the tenant’s product. |
meta.localdir | string (path) | "" | A product checkout on disk (or a folder of products, products/<product>/), read exactly as meta serves it; used when meta.url is empty. The development path. |
meta.isexternal | bool | false | The meta server sits outside the trust boundary: the service’s own certificate is not presented to it. |
api.key | string | "" | Cluster configuration: the API key presented to meta. |
A tenant with neither meta.url nor meta.localdir has no product, and so no rule sets.
Timeouts
Section titled “Timeouts”| Key | Type | Default | Effect |
|---|---|---|---|
timeouts.read | int seconds or duration string | 15s | ReadTimeout on the HTTP server. An integer is read first; only if absent is the string parsed as a duration. A parse failure logs and keeps the default. |
timeouts.write | int seconds or duration string | 15s | WriteTimeout. This is the only unconditional ceiling on a synchronous rule execution. |
timeouts.readheader | int seconds or duration string | 5s | ReadHeaderTimeout. |
timeouts.defaultcontexttimeout | duration string | 1s | Global fallback context timeout registered with the timeout checker. |
timeouts.services | list of maps | empty | Per-service timeout table. Only the entry whose name equals rules is applied; when no entry matches, previously loaded service timeouts are cleared. Loaded at boot and on every tenant refresh. |
timeouts.services[].defaultcontexttimeout | duration string | none | Default deadline for the matched service entry. |
timeouts.services[].timeouts.enabled | bool | true | Enables the matched service entry. |
timeouts.services[].pathconfig[].expr | string (regexp) | none | URL path pattern the entry applies to. Invalid patterns are logged and skipped. |
timeouts.services[].pathconfig[].duration | duration string | none | Timeout for paths matching expr. |
timeouts.services[].pathconfig[].enabled | bool | true | When false the matched path gets no timeout. |
Tenants
Section titled “Tenants”| Key | Type | Default | Effect |
|---|---|---|---|
loadtenants | list of strings | empty | Tenants whose config is fetched at boot so it is resident before the first request. Failures log warm tenant on start failed and boot continues. |
Entries must be full four-part customer:env:product:tenant keys. The refresh dispatcher requires
exactly four non-empty colon-separated parts; a short or malformed key logs a warning and returns, so
that tenant’s rules never load while the service still reports healthy and ready.
Service identity
Section titled “Service identity”| Key | Type | Default | Effect |
|---|---|---|---|
sid | string | <hostname>-rules-<port> | Service instance id: log tag, registry id, dependency-container key suffix. |
instance | string | value of sid | Config-resolution instance leaf. |
datacenter | string | default | Deployment identity tag; feeds log fields, service-discovery scoping and request context. |
cluster | string | default | Deployment identity tag. |
labels | map of string to string | none | Cohort labels used for config matching. Legacy alias tags; labels wins when both are present. |
Service discovery
Section titled “Service discovery”| Key | Type | Default | Effect |
|---|---|---|---|
servicediscovery_url | string (URL) | "" | Registry to register with. When empty a dummy client is used and the registration log line is suppressed. |
servicediscovery_apikey | string | "" | Registry API key. |
| Key | Type | Default | Effect |
|---|---|---|---|
vault.url | string (URL) | "" | A vault client is initialised and registered only when this is non-empty. Leave empty when the deployment has no Vault. |
vault.apikey | string | "" | API key for the remote vault client. |
vault.file | string (path) | "" | Local vault file, used only when vault.url is empty. |
Logging and diagnostics
Section titled “Logging and diagnostics”| Key | Type | Default | Effect |
|---|---|---|---|
log.level | string | error | trace, debug, info, warn, error, fatal, panic or disabled. An unparseable value leaves the level unchanged. |
realtimedebug | bool | false | When true, a request carrying the X-Debug-Log header or the _debug_log_ query parameter is logged at debug level for that request only. Read per request from the resolved config, so it takes effect without a restart. |
Goroutine pool
Section titled “Goroutine pool”| Key | Type | Default | Effect |
|---|---|---|---|
routinepool.size | int | 100 | Worker pool size. The listener loop and the config monitors occupy pool slots. |
routinepool.queue | int | 100 | Pool queue depth. |
routinepool.spawn | int | 50 | Pool spawn threshold. |
Keys that are read and then ignored
Section titled “Keys that are read and then ignored”| Key | Type | Reality |
|---|---|---|
defaultauthorizationaction | bool | Parsed at boot into a package variable that nothing else in the binary reads. It is not an authorization switch. |
vault.url (service copy) | string | Also copied into a package variable nothing reads. The key still has its real chassis effect above: deciding whether a vault client is created. |
Engine limits
Section titled “Engine limits”None of the engine’s execution limits are configurable. There is no flag and no configuration key for any of them. The values below are fixed for every deployment.
| Limit | Value | Configurable | Effect |
|---|---|---|---|
| Max cycles | 5000 | No | The engine re-evaluates all rule conditions in a loop; each cycle where at least one rule is runnable increments a counter. Exceeding the cap aborts the execution. |
| Rule set version | 1.0.0 | No | Every knowledge base is keyed name plus version. The service always loads and executes at the default version. |
| Abort on failed rule evaluation | true | No | Any error while evaluating a rule’s when or executing its then aborts the whole execution instead of skipping the rule. |
| Plugin set | utility built-ins plus the document plugin | No | util, num, strings, time, math, map and array are bound in every execution. The document plugin is registered as well, so bbox is bound in any execution whose request carries document input. |
Ports, health and readiness
Section titled “Ports, health and readiness”The service binds one port and registers exactly three routes: POST /rule,
GET /health and GET /ready. Both probes are registered directly on the router and short-circuit
ahead of the tenant middleware, so they need no headers and no token.
| Probe | Success | Failure | Body |
|---|---|---|---|
GET /ready | 200 | 500 | ready:true / ready:false, plain text |
GET /health | 200 | 500 | JSON with healthy, dependencies, memstats and version |
The memstats block reports Alloc, HeapAlloc, HeapSys, HeapIdle, HeapInUse, TotalAlloc
and Sys in MiB, plus NumGC as a count. It is the only built-in memory observability for this
block. dependencies is always {}. This service registers none. version is always the empty
string: the binary never sets the value the probe reports, so do not key a deployment check on it.
{ "healthy": true, "dependencies": {}, "version": ""}The response also carries a memstats object. That is runtime diagnostics, not a contract, see
API conventions. version is whatever the service
set at startup, and most set nothing.
Shutdown
Section titled “Shutdown”SIGINT or SIGTERM starts shutdown: the listener is closed, then every tenant’s watch on rules/
stops and its meta client closes.
| Step | Behaviour |
|---|---|
| Signal | SIGINT or SIGTERM |
| HTTP | The listener is closed |
| Tenants | Every tenant’s watch stops and its meta client closes |
Bootstrap example
Section titled “Bootstrap example”Every key below is read by the binary, the module ships no example configuration file.
port: "8443"host: ""log: level: infosvccert: /etc/certs/service.crtsvckey: /etc/certs/service.keyrootcacert: /etc/certs/rootca.crtzerotrust: trueconfig: url: https://config.internal apikey: <secret>api: key: <meta-api-key>loadtenants: - acme:prod:erp:eu1timeouts: read: 15s write: 60s readheader: 5sroutinepool: size: 100 queue: 100 spawn: 50Continue with
Section titled “Continue with”- Service: boot sequence, the
rules/folder and the request path - Troubleshooting: what each failure looks like and how to clear it
- Errors: the full error table and response shapes
- Rules: what compiles and runs inside a rule body
- CLI: running rules locally without the service