From e5dad2f3f0862638035bdb982d129c16f777a151 Mon Sep 17 00:00:00 2001 From: Steven van der Vegt Date: Mon, 27 Jul 2026 17:21:23 +0200 Subject: [PATCH 1/2] docs: generate server options as list-table for stable diffs The simple-table format pads every cell to the widest value in its column, so a single new option with a long description rewrites the entire table (as happened in #4420, where 2 new options produced a 142-line diff). A list-table has no cross-row alignment: adding an option is always a 3-line diff. The rendered HTML is identical, verified by diffing Sphinx output of both formats. Also removes a stray debug println from the generator. Assisted-by: AI --- docs/generate_docs.go | 6 +- docs/generate_docs_test.go | 27 ++ docs/pages/deployment/server_options.rst | 282 +++++++++++++----- .../deployment/server_options_didnuts.rst | 198 ++++++++---- docs/rst_table.go | 59 ++-- 5 files changed, 403 insertions(+), 169 deletions(-) diff --git a/docs/generate_docs.go b/docs/generate_docs.go index 9a025269e0..b91249d6b8 100644 --- a/docs/generate_docs.go +++ b/docs/generate_docs.go @@ -178,7 +178,6 @@ func extractFlagsForEngine(flagSet *pflag.FlagSet, config interface{}, engineNam } flagSet.VisitAll(func(current *pflag.Flag) { - println(current.Name, engineName) if current.Name == engineName || strings.HasPrefix(current.Name, engineName+".") { // This flag belongs to this engine, so copy it and hide it in the input flag set @@ -248,9 +247,10 @@ func generateRstTable(tableName, fileName string, values [][]rstValue) { panic(err) } defer optionsFile.Close() - optionsFile.WriteString(fmt.Sprintf(".. table:: %s\n", tableName)) + optionsFile.WriteString(fmt.Sprintf(".. list-table:: %s\n", tableName)) optionsFile.WriteString(" :widths: 20 30 50\n") - optionsFile.WriteString(" :class: options-table\n\n") + optionsFile.WriteString(" :class: options-table\n") + optionsFile.WriteString(" :header-rows: 1\n\n") printRstTable(vals("Key", "Default", "Description"), values, optionsFile) if err := optionsFile.Sync(); err != nil { panic(err) diff --git a/docs/generate_docs_test.go b/docs/generate_docs_test.go index 63b7dac39d..16124bdaf3 100644 --- a/docs/generate_docs_test.go +++ b/docs/generate_docs_test.go @@ -20,9 +20,36 @@ package main import ( "sort" + "strings" "testing" ) +func TestPrintRstTable(t *testing.T) { + var buf strings.Builder + printRstTable(vals("Key", "Default", "Description"), [][]rstValue{ + {{value: "HTTP", bold: true}}, + vals("http.public.address", ":8080", "Public address"), + vals("cpuprofile", "", "CPU profile path"), + }, &buf) + + expected := ` * - Key + - Default + - Description + * - **HTTP** + - + - + * - http.public.address + - \:8080 + - Public address + * - cpuprofile + - + - CPU profile path +` + if buf.String() != expected { + t.Errorf("unexpected list-table output:\ngot:\n%s\nwant:\n%s", buf.String(), expected) + } +} + func TestKeyList(t *testing.T) { got := KeyList{ []rstValue{{value: "storage.bbolt.backup.directory"}}, diff --git a/docs/pages/deployment/server_options.rst b/docs/pages/deployment/server_options.rst index 3fe005a037..104a22964b 100755 --- a/docs/pages/deployment/server_options.rst +++ b/docs/pages/deployment/server_options.rst @@ -1,76 +1,212 @@ -.. table:: Server Options +.. list-table:: Server Options :widths: 20 30 50 :class: options-table + :header-rows: 1 - ======================================== =================================================================================================================================================================================================================================================================================================================================================================================================================================================================== ===================================================================================================================================================================================================================================================================================================================================================== - Key Default Description - ======================================== =================================================================================================================================================================================================================================================================================================================================================================================================================================================================== ===================================================================================================================================================================================================================================================================================================================================================== - configfile ./config/nuts.yaml Nuts config file - cpuprofile When set, a CPU profile is written to the given path. Ignored when strictmode is set. - datadir ./data Directory where the node stores its files. - didmethods [web,nuts] Comma-separated list of enabled DID methods (without did: prefix). It also controls the order in which DIDs are returned by APIs, and which DID is used for signing if the verifying party does not impose restrictions on the DID method used. - internalratelimiter true When set, expensive internal calls are rate-limited to protect the network. Always enabled in strict mode. - loggerformat text Log format (text, json) - strictmode true When set, insecure settings are forbidden. - url Public facing URL of the server (required). Must be HTTPS when strictmode is set. - verbosity info Log level (trace, debug, info, warn, error) - httpclient.timeout 30s Request time-out for HTTP clients, such as '10s'. Refer to Golang's 'time.Duration' syntax for a more elaborate description of the syntax. - **Auth** - auth.authorizationendpoint.enabled false enables the v2 API's OAuth2 Authorization Endpoint, used by OpenID4VP and OpenID4VCI. This flag might be removed in a future version (or its default become 'true') as the use cases and implementation of OpenID4VP and OpenID4VCI mature. - auth.experimental.jwtbearerclient false enables the experimental RFC 7523 jwt-bearer two-VP token request flow. While disabled (the default), requests carrying a service-provider subject identifier are rejected. Subject to change without notice. - **Crypto** - crypto.storage Storage to use, 'fs' for file system (for development purposes), 'vaultkv' for HashiCorp Vault KV store, 'azure-keyvault' for Azure Key Vault, 'external' for an external backend (deprecated). - crypto.azurekv.hsm false Whether to store the key in a hardware security module (HSM). If true, the Azure Key Vault must be configured for HSM usage. Default: false - crypto.azurekv.timeout 10s Timeout of client calls to Azure Key Vault, in Golang time.Duration string format (e.g. 10s). - crypto.azurekv.url The URL of the Azure Key Vault. - crypto.azurekv.auth.type default Credential type to use when authenticating to the Azure Key Vault. Options: default, managed_identity (see https://github.com/Azure/azure-sdk-for-go/blob/main/sdk/azidentity/README.md for an explanation of the options). - crypto.vault.address The Vault address. If set it overwrites the VAULT_ADDR env var. - crypto.vault.pathprefix kv The Vault path prefix. - crypto.vault.timeout 5s Timeout of client calls to Vault, in Golang time.Duration string format (e.g. 1s). - crypto.vault.token The Vault token. If set it overwrites the VAULT_TOKEN env var. - **Discovery** - discovery.client.refreshinterval 10m0s Interval at which the client synchronizes with the Discovery Server; refreshing Verifiable Presentations of local DIDs and loading changes, updating the local copy. It only will actually refresh registrations of local DIDs that about to expire (less than 1/4th of their lifetime left). Specified as Golang duration (e.g. 1m, 1h30m). - discovery.definitions.directory ./config/discovery Directory to load Discovery Service Definitions from. If not set, the discovery service will be disabled. If the directory contains JSON files that can't be parsed as service definition, the node will fail to start. - discovery.server.ids [] IDs of the Discovery Service for which to act as server. If an ID does not map to a loaded service definition, the node will fail to start. - **HTTP** - http.clientipheader X-Forwarded-For Case-sensitive HTTP Header that contains the client IP used for audit logs. For the X-Forwarded-For header only link-local, loopback, and private IPs are excluded. Switch to X-Real-IP or a custom header if you see your own proxy/infra in the logs. - http.log metadata What to log about HTTP requests. Options are 'nothing', 'metadata' (log request method, URI, IP and response code), and 'metadata-and-body' (log the request and response body, in addition to the metadata). When debug vebosity is set the authorization headers are also logged when the request is fully logged. - http.cache.maxbytes 10485760 HTTP client maximum size of the response cache in bytes. If 0, the HTTP client does not cache responses. - http.client.allowedinternalcidrs [] IP ranges (CIDR notation, e.g. 10.0.0.0/8) exempted from the strict-mode SSRF guard, which otherwise blocks outbound requests to non-public networks. Use to permit internal flows that legitimately target a private address, such as an internal credential offering or an internal OAuth user flow. Leave empty to block all non-public addresses. - http.client.deniedcidrs [] IP ranges (CIDR notation) that outbound HTTP requests must never target in strict mode, in addition to the built-in blocked ranges (non-public addresses and cloud metadata endpoints). Use for publicly routable ranges that are internal-only in your infrastructure. Takes precedence over http.client.allowedinternalcidrs. - http.internal.address 127.0.0.1:8081 Address and port the server will be listening to for internal-facing endpoints. - http.internal.auth.audience Expected audience for JWT tokens (default: hostname) - http.internal.auth.authorizedkeyspath Path to an authorized_keys file for trusted JWT signers - http.internal.auth.type Whether to enable authentication for /internal endpoints, specify 'token_v2' for bearer token mode or 'token' for legacy bearer token mode. - http.public.address \:8080 Address and port the server will be listening to for public-facing endpoints. - **JSONLD** - jsonld.contexts.localmapping [https://nuts.nl/credentials/2024=assets/contexts/nuts-2024.ldjson,https://nuts.nl/credentials/v1=assets/contexts/nuts.ldjson,https://schema.org=assets/contexts/schema-org-v13.ldjson,https://w3c-ccg.github.io/lds-jws2020/contexts/lds-jws2020-v1.json=assets/contexts/lds-jws2020-v1.ldjson,https://w3id.org/vc/status-list/2021/v1=assets/contexts/w3c-statuslist2021.ldjson,https://www.w3.org/2018/credentials/v1=assets/contexts/w3c-credentials-v1.ldjson] This setting allows mapping external URLs to local files for e.g. preventing external dependencies. These mappings have precedence over those in remoteallowlist. - jsonld.contexts.remoteallowlist [https://schema.org,https://www.w3.org/2018/credentials/v1,https://w3c-ccg.github.io/lds-jws2020/contexts/lds-jws2020-v1.json,https://w3id.org/vc/status-list/2021/v1] In strict mode, fetching external JSON-LD contexts is not allowed except for context-URLs listed here. - **PKI** - pki.maxupdatefailhours 4 Maximum number of hours that a denylist update can fail - pki.softfail true Do not reject certificates if their revocation status cannot be established when softfail is true - **Storage** - storage.debug false When true, enables extra logging of storage-layer problems (e.g. performance issues). - storage.session.memcached.address [] List of Memcached server addresses. These can be a simple 'host:port' or a Memcached connection URL with scheme, auth and other options. - storage.session.redis.address Redis session database server address. This can be a simple 'host:port' or a Redis connection URL with scheme, auth and other options. If not set it, defaults to an in-memory database. - storage.session.redis.database Redis session database name, which is used as prefix every key. Can be used to have multiple instances use the same Redis instance. - storage.session.redis.password Redis session database password. If set, it overrides the username in the connection URL. - storage.session.redis.username Redis session database username. If set, it overrides the username in the connection URL. - storage.session.redis.sentinel.master Name of the Redis Sentinel master. Setting this property enables Redis Sentinel. - storage.session.redis.sentinel.nodes [] Addresses of the Redis Sentinels to connect to initially. Setting this property enables Redis Sentinel. - storage.session.redis.sentinel.password Password for authenticating to Redis Sentinels. - storage.session.redis.sentinel.username Username for authenticating to Redis Sentinels. - storage.session.redis.tls.truststorefile PEM file containing the trusted CA certificate(s) for authenticating remote Redis session servers. Can only be used when connecting over TLS (use 'rediss://' as scheme in address). - storage.sql.connection Connection string for the SQL database. If not set it, defaults to a SQLite database stored inside the configured data directory. Note: using SQLite is not recommended in production environments. If using SQLite anyways, remember to enable foreign keys ('_foreign_keys=on') and the write-ahead-log ('_journal_mode=WAL'). - storage.sql.rdsiam.dbuser Database username for IAM authentication. If not specified, the username from the connection string will be used. The database user must be created with IAM authentication enabled. - storage.sql.rdsiam.enabled false Enable AWS RDS IAM authentication for the SQL database connection. When enabled, the node will use temporary IAM tokens instead of passwords. Requires the connection string to be a PostgreSQL or MySQL RDS endpoint without a password. - storage.sql.rdsiam.region AWS region where the RDS instance is located (e.g., 'us-east-1). Required when RDS IAM authentication is enabled. - storage.sql.rdsiam.tokenrefreshinterval 14m0s Interval at which to refresh the IAM authentication token. RDS tokens are valid for 15 minutes, so set this to ensure tokens are refreshed before expiry. Specified as Golang duration (e.g. 10m, 1h). - **Tracing** - tracing.endpoint OTLP collector endpoint for OpenTelemetry tracing (e.g., 'localhost:4318'). When empty, tracing is disabled. - tracing.insecure false Disable TLS for the OTLP connection. - tracing.servicename Service name reported to the tracing backend. Defaults to 'nuts-node'. - **policy** - policy.directory ./config/policy Directory to read policy files from. Policy files are JSON files that contain a scope to PresentationDefinition mapping. - policy.authzen.endpoint Base URL of the AuthZen PDP endpoint. Required when any credential profile uses scope_policy 'dynamic'; the node refuses to start if such a profile is configured but this flag is empty. - ======================================== =================================================================================================================================================================================================================================================================================================================================================================================================================================================================== ===================================================================================================================================================================================================================================================================================================================================================== + * - Key + - Default + - Description + * - configfile + - ./config/nuts.yaml + - Nuts config file + * - cpuprofile + - + - When set, a CPU profile is written to the given path. Ignored when strictmode is set. + * - datadir + - ./data + - Directory where the node stores its files. + * - didmethods + - [web,nuts] + - Comma-separated list of enabled DID methods (without did: prefix). It also controls the order in which DIDs are returned by APIs, and which DID is used for signing if the verifying party does not impose restrictions on the DID method used. + * - internalratelimiter + - true + - When set, expensive internal calls are rate-limited to protect the network. Always enabled in strict mode. + * - loggerformat + - text + - Log format (text, json) + * - strictmode + - true + - When set, insecure settings are forbidden. + * - url + - + - Public facing URL of the server (required). Must be HTTPS when strictmode is set. + * - verbosity + - info + - Log level (trace, debug, info, warn, error) + * - httpclient.timeout + - 30s + - Request time-out for HTTP clients, such as '10s'. Refer to Golang's 'time.Duration' syntax for a more elaborate description of the syntax. + * - **Auth** + - + - + * - auth.authorizationendpoint.enabled + - false + - enables the v2 API's OAuth2 Authorization Endpoint, used by OpenID4VP and OpenID4VCI. This flag might be removed in a future version (or its default become 'true') as the use cases and implementation of OpenID4VP and OpenID4VCI mature. + * - auth.experimental.jwtbearerclient + - false + - enables the experimental RFC 7523 jwt-bearer two-VP token request flow. While disabled (the default), requests carrying a service-provider subject identifier are rejected. Subject to change without notice. + * - **Crypto** + - + - + * - crypto.storage + - + - Storage to use, 'fs' for file system (for development purposes), 'vaultkv' for HashiCorp Vault KV store, 'azure-keyvault' for Azure Key Vault, 'external' for an external backend (deprecated). + * - crypto.azurekv.hsm + - false + - Whether to store the key in a hardware security module (HSM). If true, the Azure Key Vault must be configured for HSM usage. Default: false + * - crypto.azurekv.timeout + - 10s + - Timeout of client calls to Azure Key Vault, in Golang time.Duration string format (e.g. 10s). + * - crypto.azurekv.url + - + - The URL of the Azure Key Vault. + * - crypto.azurekv.auth.type + - default + - Credential type to use when authenticating to the Azure Key Vault. Options: default, managed_identity (see https://github.com/Azure/azure-sdk-for-go/blob/main/sdk/azidentity/README.md for an explanation of the options). + * - crypto.vault.address + - + - The Vault address. If set it overwrites the VAULT_ADDR env var. + * - crypto.vault.pathprefix + - kv + - The Vault path prefix. + * - crypto.vault.timeout + - 5s + - Timeout of client calls to Vault, in Golang time.Duration string format (e.g. 1s). + * - crypto.vault.token + - + - The Vault token. If set it overwrites the VAULT_TOKEN env var. + * - **Discovery** + - + - + * - discovery.client.refreshinterval + - 10m0s + - Interval at which the client synchronizes with the Discovery Server; refreshing Verifiable Presentations of local DIDs and loading changes, updating the local copy. It only will actually refresh registrations of local DIDs that about to expire (less than 1/4th of their lifetime left). Specified as Golang duration (e.g. 1m, 1h30m). + * - discovery.definitions.directory + - ./config/discovery + - Directory to load Discovery Service Definitions from. If not set, the discovery service will be disabled. If the directory contains JSON files that can't be parsed as service definition, the node will fail to start. + * - discovery.server.ids + - [] + - IDs of the Discovery Service for which to act as server. If an ID does not map to a loaded service definition, the node will fail to start. + * - **HTTP** + - + - + * - http.clientipheader + - X-Forwarded-For + - Case-sensitive HTTP Header that contains the client IP used for audit logs. For the X-Forwarded-For header only link-local, loopback, and private IPs are excluded. Switch to X-Real-IP or a custom header if you see your own proxy/infra in the logs. + * - http.log + - metadata + - What to log about HTTP requests. Options are 'nothing', 'metadata' (log request method, URI, IP and response code), and 'metadata-and-body' (log the request and response body, in addition to the metadata). When debug vebosity is set the authorization headers are also logged when the request is fully logged. + * - http.cache.maxbytes + - 10485760 + - HTTP client maximum size of the response cache in bytes. If 0, the HTTP client does not cache responses. + * - http.client.allowedinternalcidrs + - [] + - IP ranges (CIDR notation, e.g. 10.0.0.0/8) exempted from the strict-mode SSRF guard, which otherwise blocks outbound requests to non-public networks. Use to permit internal flows that legitimately target a private address, such as an internal credential offering or an internal OAuth user flow. Leave empty to block all non-public addresses. + * - http.client.deniedcidrs + - [] + - IP ranges (CIDR notation) that outbound HTTP requests must never target in strict mode, in addition to the built-in blocked ranges (non-public addresses and cloud metadata endpoints). Use for publicly routable ranges that are internal-only in your infrastructure. Takes precedence over http.client.allowedinternalcidrs. + * - http.internal.address + - 127.0.0.1:8081 + - Address and port the server will be listening to for internal-facing endpoints. + * - http.internal.auth.audience + - + - Expected audience for JWT tokens (default: hostname) + * - http.internal.auth.authorizedkeyspath + - + - Path to an authorized_keys file for trusted JWT signers + * - http.internal.auth.type + - + - Whether to enable authentication for /internal endpoints, specify 'token_v2' for bearer token mode or 'token' for legacy bearer token mode. + * - http.public.address + - \:8080 + - Address and port the server will be listening to for public-facing endpoints. + * - **JSONLD** + - + - + * - jsonld.contexts.localmapping + - [https://nuts.nl/credentials/2024=assets/contexts/nuts-2024.ldjson,https://nuts.nl/credentials/v1=assets/contexts/nuts.ldjson,https://schema.org=assets/contexts/schema-org-v13.ldjson,https://w3c-ccg.github.io/lds-jws2020/contexts/lds-jws2020-v1.json=assets/contexts/lds-jws2020-v1.ldjson,https://w3id.org/vc/status-list/2021/v1=assets/contexts/w3c-statuslist2021.ldjson,https://www.w3.org/2018/credentials/v1=assets/contexts/w3c-credentials-v1.ldjson] + - This setting allows mapping external URLs to local files for e.g. preventing external dependencies. These mappings have precedence over those in remoteallowlist. + * - jsonld.contexts.remoteallowlist + - [https://schema.org,https://www.w3.org/2018/credentials/v1,https://w3c-ccg.github.io/lds-jws2020/contexts/lds-jws2020-v1.json,https://w3id.org/vc/status-list/2021/v1] + - In strict mode, fetching external JSON-LD contexts is not allowed except for context-URLs listed here. + * - **PKI** + - + - + * - pki.maxupdatefailhours + - 4 + - Maximum number of hours that a denylist update can fail + * - pki.softfail + - true + - Do not reject certificates if their revocation status cannot be established when softfail is true + * - **Storage** + - + - + * - storage.debug + - false + - When true, enables extra logging of storage-layer problems (e.g. performance issues). + * - storage.session.memcached.address + - [] + - List of Memcached server addresses. These can be a simple 'host:port' or a Memcached connection URL with scheme, auth and other options. + * - storage.session.redis.address + - + - Redis session database server address. This can be a simple 'host:port' or a Redis connection URL with scheme, auth and other options. If not set it, defaults to an in-memory database. + * - storage.session.redis.database + - + - Redis session database name, which is used as prefix every key. Can be used to have multiple instances use the same Redis instance. + * - storage.session.redis.password + - + - Redis session database password. If set, it overrides the username in the connection URL. + * - storage.session.redis.username + - + - Redis session database username. If set, it overrides the username in the connection URL. + * - storage.session.redis.sentinel.master + - + - Name of the Redis Sentinel master. Setting this property enables Redis Sentinel. + * - storage.session.redis.sentinel.nodes + - [] + - Addresses of the Redis Sentinels to connect to initially. Setting this property enables Redis Sentinel. + * - storage.session.redis.sentinel.password + - + - Password for authenticating to Redis Sentinels. + * - storage.session.redis.sentinel.username + - + - Username for authenticating to Redis Sentinels. + * - storage.session.redis.tls.truststorefile + - + - PEM file containing the trusted CA certificate(s) for authenticating remote Redis session servers. Can only be used when connecting over TLS (use 'rediss://' as scheme in address). + * - storage.sql.connection + - + - Connection string for the SQL database. If not set it, defaults to a SQLite database stored inside the configured data directory. Note: using SQLite is not recommended in production environments. If using SQLite anyways, remember to enable foreign keys ('_foreign_keys=on') and the write-ahead-log ('_journal_mode=WAL'). + * - storage.sql.rdsiam.dbuser + - + - Database username for IAM authentication. If not specified, the username from the connection string will be used. The database user must be created with IAM authentication enabled. + * - storage.sql.rdsiam.enabled + - false + - Enable AWS RDS IAM authentication for the SQL database connection. When enabled, the node will use temporary IAM tokens instead of passwords. Requires the connection string to be a PostgreSQL or MySQL RDS endpoint without a password. + * - storage.sql.rdsiam.region + - + - AWS region where the RDS instance is located (e.g., 'us-east-1). Required when RDS IAM authentication is enabled. + * - storage.sql.rdsiam.tokenrefreshinterval + - 14m0s + - Interval at which to refresh the IAM authentication token. RDS tokens are valid for 15 minutes, so set this to ensure tokens are refreshed before expiry. Specified as Golang duration (e.g. 10m, 1h). + * - **Tracing** + - + - + * - tracing.endpoint + - + - OTLP collector endpoint for OpenTelemetry tracing (e.g., 'localhost:4318'). When empty, tracing is disabled. + * - tracing.insecure + - false + - Disable TLS for the OTLP connection. + * - tracing.servicename + - + - Service name reported to the tracing backend. Defaults to 'nuts-node'. + * - **policy** + - + - + * - policy.directory + - ./config/policy + - Directory to read policy files from. Policy files are JSON files that contain a scope to PresentationDefinition mapping. + * - policy.authzen.endpoint + - + - Base URL of the AuthZen PDP endpoint. Required when any credential profile uses scope_policy 'dynamic'; the node refuses to start if such a profile is configured but this flag is empty. diff --git a/docs/pages/deployment/server_options_didnuts.rst b/docs/pages/deployment/server_options_didnuts.rst index 254939cf20..584970a1ec 100755 --- a/docs/pages/deployment/server_options_didnuts.rst +++ b/docs/pages/deployment/server_options_didnuts.rst @@ -1,55 +1,149 @@ -.. table:: did:nuts/gRPC Server Options +.. list-table:: did:nuts/gRPC Server Options :widths: 20 30 50 :class: options-table + :header-rows: 1 - ================================ =========================== ====================================================================================================================================================================================== - Key Default Description - ================================ =========================== ====================================================================================================================================================================================== - tls.certfile PEM file containing the certificate for the gRPC server (also used as client certificate). Required in strict mode. - tls.certheader Name of the HTTP header that will contain the client certificate when TLS is offloaded for gRPC. - tls.certkeyfile PEM file containing the private key of the gRPC server certificate. Required in strict mode. - tls.offload Whether to enable TLS offloading for incoming gRPC connections. Enable by setting it to 'incoming'. If enabled 'tls.certheader' must be configured as well. - tls.truststorefile ./config/ssl/truststore.pem PEM file containing the trusted CA certificates for authenticating remote gRPC servers. Required in strict mode. - **Auth** - auth.accesstokenlifespan 60 defines how long (in seconds) an access token is valid. Uses default in strict mode. - auth.clockskew 5000 allowed JWT Clock skew in milliseconds - auth.contractvalidators [irma,dummy,employeeid] sets the different contract validators to use - auth.irma.autoupdateschemas true set if you want automatically update the IRMA schemas every 60 minutes. - auth.irma.schememanager pbdf IRMA schemeManager to use for attributes. Can be either 'pbdf' or 'irma-demo'. - auth.irma.cors.origin [] sets the allowed CORS origins for the IRMA server - **Events** - events.nats.hostname 0.0.0.0 Hostname for the NATS server - events.nats.port 4222 Port where the NATS server listens on - events.nats.storagedir Directory where file-backed streams are stored in the NATS server - events.nats.timeout 30 Timeout for NATS server operations - **GoldenHammer** - goldenhammer.enabled true Whether to enable automatically fixing DID documents with the required endpoints. - goldenhammer.interval 10m0s The interval in which to check for DID documents to fix. - **Network** - network.bootstrapnodes [] List of bootstrap nodes (':') which the node initially connect to. - network.connectiontimeout 5000 Timeout before an outbound connection attempt times out (in milliseconds). - network.enablediscovery true Whether to enable automatic connecting to other nodes. - network.grpcaddr \:5555 Local address for gRPC to listen on. If empty the gRPC server won't be started and other nodes will not be able to connect to this node (outbound connections can still be made). - network.maxbackoff 24h0m0s Maximum between outbound connections attempts to unresponsive nodes (in Golang duration format, e.g. '1h', '30m'). - network.nodedid Specifies the DID of the party that operates this node. It is used to identify the node on the network. If the DID document does not exist of is deactivated, the node will not start. - network.protocols [] Specifies the list of network protocols to enable on the server. They are specified by version (1, 2). If not set, all protocols are enabled. - network.v2.diagnosticsinterval 5000 Interval (in milliseconds) that specifies how often the node should broadcast its diagnostic information to other nodes (specify 0 to disable). - network.v2.gossipinterval 5000 Interval (in milliseconds) that specifies how often the node should gossip its new hashes to other nodes. - **Storage** - storage.bbolt.locktimeout 1s Maximum time to wait for acquiring a lock on the BBolt database before giving up and returning an error. Formatted as Golang duration (e.g. 1s, 1m). - storage.bbolt.backup.directory Target directory for BBolt database backups. - storage.bbolt.backup.interval 0s Interval, formatted as Golang duration (e.g. 10m, 1h) at which BBolt database backups will be performed. - storage.redis.address Redis database server address. This can be a simple 'host:port' or a Redis connection URL with scheme, auth and other options. - storage.redis.database Redis database name, which is used as prefix every key. Can be used to have multiple instances use the same Redis instance. - storage.redis.password Redis database password. If set, it overrides the username in the connection URL. - storage.redis.username Redis database username. If set, it overrides the username in the connection URL. - storage.redis.sentinel.master Name of the Redis Sentinel master. Setting this property enables Redis Sentinel. - storage.redis.sentinel.nodes [] Addresses of the Redis Sentinels to connect to initially. Setting this property enables Redis Sentinel. - storage.redis.sentinel.password Password for authenticating to Redis Sentinels. - storage.redis.sentinel.username Username for authenticating to Redis Sentinels. - storage.redis.tls.truststorefile PEM file containing the trusted CA certificate(s) for authenticating remote Redis servers. Can only be used when connecting over TLS (use 'rediss://' as scheme in address). - **VCR** - vcr.openid4vci.definitionsdir Directory with the additional credential definitions the node could issue (experimental, may change without notice). - vcr.openid4vci.enabled true Enable issuing and receiving credentials over OpenID4VCI. - vcr.openid4vci.timeout 30s Time-out for OpenID4VCI HTTP client operations. - ================================ =========================== ====================================================================================================================================================================================== + * - Key + - Default + - Description + * - tls.certfile + - + - PEM file containing the certificate for the gRPC server (also used as client certificate). Required in strict mode. + * - tls.certheader + - + - Name of the HTTP header that will contain the client certificate when TLS is offloaded for gRPC. + * - tls.certkeyfile + - + - PEM file containing the private key of the gRPC server certificate. Required in strict mode. + * - tls.offload + - + - Whether to enable TLS offloading for incoming gRPC connections. Enable by setting it to 'incoming'. If enabled 'tls.certheader' must be configured as well. + * - tls.truststorefile + - ./config/ssl/truststore.pem + - PEM file containing the trusted CA certificates for authenticating remote gRPC servers. Required in strict mode. + * - **Auth** + - + - + * - auth.accesstokenlifespan + - 60 + - defines how long (in seconds) an access token is valid. Uses default in strict mode. + * - auth.clockskew + - 5000 + - allowed JWT Clock skew in milliseconds + * - auth.contractvalidators + - [irma,dummy,employeeid] + - sets the different contract validators to use + * - auth.irma.autoupdateschemas + - true + - set if you want automatically update the IRMA schemas every 60 minutes. + * - auth.irma.schememanager + - pbdf + - IRMA schemeManager to use for attributes. Can be either 'pbdf' or 'irma-demo'. + * - auth.irma.cors.origin + - [] + - sets the allowed CORS origins for the IRMA server + * - **Events** + - + - + * - events.nats.hostname + - 0.0.0.0 + - Hostname for the NATS server + * - events.nats.port + - 4222 + - Port where the NATS server listens on + * - events.nats.storagedir + - + - Directory where file-backed streams are stored in the NATS server + * - events.nats.timeout + - 30 + - Timeout for NATS server operations + * - **GoldenHammer** + - + - + * - goldenhammer.enabled + - true + - Whether to enable automatically fixing DID documents with the required endpoints. + * - goldenhammer.interval + - 10m0s + - The interval in which to check for DID documents to fix. + * - **Network** + - + - + * - network.bootstrapnodes + - [] + - List of bootstrap nodes (':') which the node initially connect to. + * - network.connectiontimeout + - 5000 + - Timeout before an outbound connection attempt times out (in milliseconds). + * - network.enablediscovery + - true + - Whether to enable automatic connecting to other nodes. + * - network.grpcaddr + - \:5555 + - Local address for gRPC to listen on. If empty the gRPC server won't be started and other nodes will not be able to connect to this node (outbound connections can still be made). + * - network.maxbackoff + - 24h0m0s + - Maximum between outbound connections attempts to unresponsive nodes (in Golang duration format, e.g. '1h', '30m'). + * - network.nodedid + - + - Specifies the DID of the party that operates this node. It is used to identify the node on the network. If the DID document does not exist of is deactivated, the node will not start. + * - network.protocols + - [] + - Specifies the list of network protocols to enable on the server. They are specified by version (1, 2). If not set, all protocols are enabled. + * - network.v2.diagnosticsinterval + - 5000 + - Interval (in milliseconds) that specifies how often the node should broadcast its diagnostic information to other nodes (specify 0 to disable). + * - network.v2.gossipinterval + - 5000 + - Interval (in milliseconds) that specifies how often the node should gossip its new hashes to other nodes. + * - **Storage** + - + - + * - storage.bbolt.locktimeout + - 1s + - Maximum time to wait for acquiring a lock on the BBolt database before giving up and returning an error. Formatted as Golang duration (e.g. 1s, 1m). + * - storage.bbolt.backup.directory + - + - Target directory for BBolt database backups. + * - storage.bbolt.backup.interval + - 0s + - Interval, formatted as Golang duration (e.g. 10m, 1h) at which BBolt database backups will be performed. + * - storage.redis.address + - + - Redis database server address. This can be a simple 'host:port' or a Redis connection URL with scheme, auth and other options. + * - storage.redis.database + - + - Redis database name, which is used as prefix every key. Can be used to have multiple instances use the same Redis instance. + * - storage.redis.password + - + - Redis database password. If set, it overrides the username in the connection URL. + * - storage.redis.username + - + - Redis database username. If set, it overrides the username in the connection URL. + * - storage.redis.sentinel.master + - + - Name of the Redis Sentinel master. Setting this property enables Redis Sentinel. + * - storage.redis.sentinel.nodes + - [] + - Addresses of the Redis Sentinels to connect to initially. Setting this property enables Redis Sentinel. + * - storage.redis.sentinel.password + - + - Password for authenticating to Redis Sentinels. + * - storage.redis.sentinel.username + - + - Username for authenticating to Redis Sentinels. + * - storage.redis.tls.truststorefile + - + - PEM file containing the trusted CA certificate(s) for authenticating remote Redis servers. Can only be used when connecting over TLS (use 'rediss://' as scheme in address). + * - **VCR** + - + - + * - vcr.openid4vci.definitionsdir + - + - Directory with the additional credential definitions the node could issue (experimental, may change without notice). + * - vcr.openid4vci.enabled + - true + - Enable issuing and receiving credentials over OpenID4VCI. + * - vcr.openid4vci.timeout + - 30s + - Time-out for OpenID4VCI HTTP client operations. diff --git a/docs/rst_table.go b/docs/rst_table.go index 65f7ed9959..e969f42c8e 100644 --- a/docs/rst_table.go +++ b/docs/rst_table.go @@ -24,58 +24,35 @@ import ( "strings" ) +// printRstTable renders the rows as the content of a list-table directive. +// Each row is a self-contained block, so adding or changing a row never reformats +// the other rows (unlike a simple table, where every cell is padded to the widest +// value in its column and a single long value rewrites the entire table). func printRstTable(header []rstValue, values [][]rstValue, writer io.StringWriter) { - columnLengths := make([]int, len(header)) - rows := make([][]rstValue, len(values)+1) - rows[0] = header - for i, row := range values { - rows[i+1] = row + printRow(header, len(header), writer) + for _, row := range values { + printRow(row, len(header), writer) } - for _, row := range rows { - for i := 0; i < len(row); i++ { - columnLengths[i] = intMax(columnLengths[i], len(row[i].value)) - } - } - dividers := []rstValue{ - {value: strings.Repeat("=", columnLengths[0])}, - {value: strings.Repeat("=", columnLengths[1])}, - {value: strings.Repeat("=", columnLengths[2])}, - } - printRow(dividers, columnLengths, writer) - printRow(rows[0], columnLengths, writer) - printRow(dividers, columnLengths, writer) - for i, row := range rows { - if i == 0 { - // Skip headers - continue - } - printRow(row, columnLengths, writer) - } - printRow(dividers, columnLengths, writer) } -func printRow(values []rstValue, columnLengths []int, writer io.StringWriter) { - first := true - for i := 0; i < len(columnLengths); i++ { - if !first { - writer.WriteString(" ") +func printRow(values []rstValue, columns int, writer io.StringWriter) { + for i := 0; i < columns; i++ { + prefix := " * - " + if i > 0 { + prefix = " - " } cell := rstValue{} // Account for a row with less values than columns in the table if i < len(values) { cell = values[i] } - writer.WriteString(" " + cell.render() + strings.Repeat(" ", columnLengths[i]-len(cell.value))) - first = false - } - writer.WriteString("\n") -} - -func intMax(a int, b int) int { - if a > b { - return a + rendered := cell.render() + if rendered == "" { + // Avoid trailing whitespace on empty cells + prefix = strings.TrimRight(prefix, " ") + } + writer.WriteString(prefix + rendered + "\n") } - return b } type rstValue struct { From 92bea62e69c52b774bd05d3d727da41619be6e5b Mon Sep 17 00:00:00 2001 From: Steven van der Vegt Date: Mon, 27 Jul 2026 17:23:35 +0200 Subject: [PATCH 2/2] build: add docs-docker Makefile target for containerized Sphinx builds The docs/Dockerfile existed but nothing referenced it. The new target builds the documentation without requiring Python/Sphinx on the host. Assisted-by: AI --- makefile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/makefile b/makefile index bec1275f5a..b506f054f5 100644 --- a/makefile +++ b/makefile @@ -103,6 +103,12 @@ cli-docs: go run ./docs docs rst_include include README_template.rst README.rst +# Builds the Sphinx documentation in a container, so no Python/Sphinx tooling +# is needed on the host. Output lands in docs/_build/html. +docs-docker: + docker build -t nuts-node-docs docs/ + docker run --rm -v ${DIR}/docs:/docs nuts-node-docs + all-docs: cli-docs gen-diagrams fix-copyright: