Node Configuration Reference
This page is not normative
This page is not considered a core part of the Vultron Protocol as proposed in the main documentation. Although within the page we might provide guidance in terms of SHOULD, MUST, etc., the content here is not normative.
This page lists every setting a node of the Vultron reference implementation reads at startup, with the config.yaml key and the environment variable for each one.
It covers the API server process, vultron.adapters.driving.fastapi.main:app, whether it runs in a container or directly under uvicorn.
The settings tables and the example file are generated from the configuration model in vultron/config/ when the site is built, so they list the settings, types and defaults that the build itself uses.
Configuration sources
A node builds its configuration from three sources: environment variables, a configuration file written in YAML Ain't Markup Language (YAML), and the defaults. A source higher in the table overrides a source below it, one setting at a time (CFG-02-004).
| Source | Where it is read from | When it applies |
|---|---|---|
| Environment variables | VULTRON_* variables in the server process environment |
Each variable that is set overrides the same setting from the file |
| Configuration file | The YAML file named by VULTRON_CONFIG, or config.yaml in the working directory when VULTRON_CONFIG is unset |
Each key present in the file overrides the default |
| Defaults | The configuration model | Every setting has one, so a node starts with no file and no variables (CFG-02-005) |
VULTRON_CONFIG holds a file path, relative to the working directory or absolute (CFG-02-002).
When VULTRON_CONFIG names a file that does not exist, the node refuses to start and reports the path (CFG-02-006).
When VULTRON_CONFIG is unset and no config.yaml exists in the working directory, the node starts on defaults and environment variables alone (CFG-02-007).
An unknown key at the top level of the file stops the node at startup.
An unknown key inside a section, such as a misspelled server: key, is ignored without a warning, so check each section key against the tables below.
A node reads its configuration once and keeps it for the life of the process. A change to the file or to the environment takes effect when the server restarts.
Environment variable names
Every environment variable name is VULTRON_ followed by the setting's YAML key path in upper case (CFG-03-001).
A double underscore, __, separates a section from the key inside it (CFG-03-002).
| YAML key | Environment variable |
|---|---|
mode |
VULTRON_MODE |
server.base_url |
VULTRON_SERVER__BASE_URL |
actor.case_actor_service_url |
VULTRON_ACTOR__CASE_ACTOR_SERVICE_URL |
A single underscore inside a key stays a single underscore: ledger.staleness_window_days is VULTRON_LEDGER__STALENESS_WINDOW_DAYS.
Value formats
An environment variable always carries a string, so a setting whose type is not a string has a text form for the environment.
| Type | In config.yaml |
In an environment variable |
|---|---|---|
| string, URL | A YAML string | The text itself |
| integer, number | A YAML number | The number as text, for example 300 or 0.25 |
| boolean | true or false |
true or false |
| duration | An ISO 8601 duration string, for example PT72H or P7D, or a number of seconds |
A duration string, preferably ISO 8601; a bare number of seconds is refused |
| list | A YAML sequence | A JSON array, for example ["vendor", "coordinator"] |
| unset | null, or the key left out |
No form: a variable left out of the environment leaves the setting at its file value or default |
A value that does not match its setting's type or bounds stops the node at startup with an error that names the setting.
A list variable that is not a valid JSON array also stops the node, but its error names only the section, for example actor.
A ledger.invite_resend_max_cooldown_seconds set below ledger.invite_resend_cooldown_seconds stops the node too.
Settings
Each table below lists one section of config.yaml.
The Type column gives the accepted values and any numeric bounds, and the Default column gives the value the node uses when neither the file nor the environment sets one.
Top-level settings
| YAML key | Environment variable | Type | Default | Description |
|---|---|---|---|---|
mode |
VULTRON_MODE |
string, one of prototype, prod |
prototype |
Operational mode (prototype or prod). |
pre_bootstrap_queue_timeout_seconds |
VULTRON_PRE_BOOTSTRAP_QUEUE_TIMEOUT_SECONDS |
integer | 300 |
How long (in seconds) a pre-bootstrap inbox queue is held before it expires. When the window lapses, queued activity IDs are dropped and a warning is logged (CBT-03-003, CBT-03-005, CBT-03-006). |
max_inbox_retry_attempts |
VULTRON_MAX_INBOX_RETRY_ATTEMPTS |
integer | 12 |
Maximum cumulative processing attempts for a single inbox activity before it is moved to the dead-letter store (IE-06-004). Matches the outbox default of 12 so that inbox and outbox share the same retry budget. |
max_object_fetch_attempts |
VULTRON_MAX_OBJECT_FETCH_ATTEMPTS |
integer (≥ 1) | 3 |
Maximum attempts to fetch one object a received activity names before the fetch fails and the waiting activity goes on without it (AKM-05-008). Attempts back off exponentially; a 4xx answer ends the fetch at once. |
object_fetch_timeout_seconds |
VULTRON_OBJECT_FETCH_TIMEOUT_SECONDS |
number (> 0) | 30.0 |
Timeout of each fetch attempt, in seconds (AKM-05-008). It matches the delivery timeout (SYNC-05-004). |
server: section
| YAML key | Environment variable | Type | Default | Description |
|---|---|---|---|---|
server.base_url |
VULTRON_SERVER__BASE_URL |
string | http://localhost:7999/api/v2 |
Base URL of the Vultron server, used for constructing object IDs. It starts with http:// or https://. The value includes the API path prefix: an actor's id is the URL that reaches it, and a hosted actor is named {base_url}/actors/{slug}, so a value without /api/v2 mints ids that address nothing (DL-07-006). The default has the shape the compose files set, so a local run resolves actors the way a deployed one does. |
server.log_level |
VULTRON_SERVER__LOG_LEVEL |
string, one of DEBUG, INFO, WARNING, ERROR, CRITICAL |
INFO |
Root log level name. Must be one of DEBUG, INFO, WARNING, ERROR, or CRITICAL. |
server.ledger_stream_poll_seconds |
VULTRON_SERVER__LEDGER_STREAM_POLL_SECONDS |
number (> 0) | 0.25 |
How often (in seconds) an open demo case ledger stream re-reads the actor's DataLayer for new entries (GET /actors/{id}/demo/cases/{case_id}/log/stream, ADR-0104). Must be positive. |
database: section
| YAML key | Environment variable | Type | Default | Description |
|---|---|---|---|---|
database.db_url |
VULTRON_DATABASE__DB_URL |
string | sqlite:///vultron.db |
SQLAlchemy connection URL. |
actor: section
| YAML key | Environment variable | Type | Default | Description |
|---|---|---|---|---|
actor.default_case_roles |
VULTRON_ACTOR__DEFAULT_CASE_ROLES |
list of strings, each one of reporter, vendor, deployer, coordinator, observer, case_owner, case_manager, cve_numbering_authority |
[] |
CVD roles assigned to the local actor when it creates or receives ownership of a VulnerabilityCase. CVDRole.CASE_OWNER is always appended at participant-creation time (BTND-05-002). |
actor.auto_create_case |
VULTRON_ACTOR__AUTO_CREATE_CASE |
boolean | true |
When true, create a VulnerabilityCase immediately on Offer(VulnerabilityReport) receipt (CM-15-001, CM-12-001, CM-22-001). When false, defer case creation so the receiver can send a pre-case ACK (Read(Offer(VulnerabilityReport)), VAM-02-003) before deciding to accept or reject (CM-15-002, CM-15-003; ADR-0015). |
actor.case_actor_service_url |
VULTRON_ACTOR__CASE_ACTOR_SERVICE_URL |
HTTP(S) URL, or unset | unset | Base URL of the dedicated CaseActor service (e.g. http://case-actor:7999/api/v2). The CaseActor's identity is {this}/actors/case-actor — one per container, no per-case slug (CP-04-005). Required for any actor whose BT may run the engage-case path. When it is unset, the nodes that need it fail with a clear error rather than guess a base URL, since a guessed identity is one no container hosts (CP-08-001, CP-08-002). |
actor.min_rsvp_window |
VULTRON_ACTOR__MIN_RSVP_WINDOW |
duration | P3D |
Minimum time between now and an RSVP deadline on an outbound Invite(EmbargoEvent). Outbound invites below this floor are refused at construction time (EP-07-002). Inbound invites below this floor are clamped up to the floor (EP-07-003). |
actor.default_rsvp_window |
VULTRON_ACTOR__DEFAULT_RSVP_WINDOW |
duration | P7D |
Fallback RSVP window used when no explicit deadline is provided on an outbound Invite(EmbargoEvent) (EP-07-001). |
actor.protocol_default_embargo_duration |
VULTRON_ACTOR__PROTOCOL_DEFAULT_EMBARGO_DURATION |
duration | P3D |
Embargo duration applied at case creation when neither a sender proposal nor an actor default (published EmbargoPolicy) applies. Constrained to [72 hours, 5 days]; a value outside that range is refused (EP-04-018, EP-04-032, ADR-0096). It never competes under shortest-wins and is never a minimum on agreed terms (EP-04-006, EP-04-007). |
actor.post_close_reply |
VULTRON_ACTOR__POST_CLOSE_REPLY |
string, one of drop, reject |
drop |
The one policy point for replies after the case closes: whether the CASE_MANAGER answers a late Leave(VulnerabilityCase) with an as:Reject or drops it. Every other late activity is dropped under either setting (CM-23-017, CM-23-045, ADR-0131). |
ledger: section
| YAML key | Environment variable | Type | Default | Description |
|---|---|---|---|---|
ledger.clock_skew_tolerance_seconds |
VULTRON_LEDGER__CLOCK_SKEW_TOLERANCE_SECONDS |
integer (≥ 0) | 300 |
How far before the parent case's own published timestamp an assertion's claimed timestamp may fall before CLP-14-006 rejects it. A non-zero tolerance is required because participant and CaseActor clocks are not synchronized — ADR-0079 rejected wall-clock ordering (option C) for exactly this reason. The default matches the CLP-14-007 convention. |
ledger.future_tolerance_seconds |
VULTRON_LEDGER__FUTURE_TOLERANCE_SECONDS |
integer (≥ 0) | 300 |
How far ahead of the CaseActor's own clock an assertion's claimed timestamp may fall before CLP-14-007 rejects it. CLP-14-007 sets the default ceiling at five minutes. |
ledger.staleness_window_days |
VULTRON_LEDGER__STALENESS_WINDOW_DAYS |
integer (≥ 0) | 7 |
How far behind the CaseActor's own clock an assertion's claimed timestamp may fall before CLP-14-008 rejects it. CLP-14-008 sets the default at seven days. |
ledger.position_statement_interval_seconds |
VULTRON_LEDGER__POSITION_STATEMENT_INTERVAL_SECONDS |
integer (≥ 1), or unset | unset | How often a hosted participant states its ledger position for each case it holds, with Read(CaseLedgerEntry), beyond the statement it sends after every restart (SYNC-17-007). When it is unset the periodic statement is off, because a periodic check costs traffic a deployment should choose. |
ledger.invite_resend_cooldown_seconds |
VULTRON_LEDGER__INVITE_RESEND_COOLDOWN_SECONDS |
number (> 0) | 30.0 |
The base cooldown between two resends of one unanswered Invite to one participant (SYNC-20-005). Each consecutive resend doubles it. It matches the base of the ledger replay cooldown (SYNC-15-013). |
ledger.invite_resend_max_cooldown_seconds |
VULTRON_LEDGER__INVITE_RESEND_MAX_COOLDOWN_SECONDS |
number (> 0) | 600.0 |
The ceiling the doubled resend cooldown stops at, so an unanswered Invite is still resent at a fixed interval until its deadline (SYNC-20-005). It matches the replay cooldown's ceiling, and a value below invite_resend_cooldown_seconds is refused at load. |
actor.case_actor_service_url has no default, and a node that receives reports needs it.
Without it, the node cannot ask the CaseActor service to open a case for a report it receives (CP-08-001).
The proposal flow that uses it is described in Propose Case.
Example configuration file
The file below sets every setting to its default, in the YAML form the node reads. A file that sets only some keys is equivalent to this one with the remaining keys left at these values.
server:
base_url: http://localhost:7999/api/v2
log_level: INFO
ledger_stream_poll_seconds: 0.25
database:
db_url: sqlite:///vultron.db
actor:
default_case_roles: []
auto_create_case: true
case_actor_service_url: null
min_rsvp_window: P3D
default_rsvp_window: P7D
protocol_default_embargo_duration: P3D
post_close_reply: drop
ledger:
clock_skew_tolerance_seconds: 300
future_tolerance_seconds: 300
staleness_window_days: 7
position_statement_interval_seconds: null
invite_resend_cooldown_seconds: 30.0
invite_resend_max_cooldown_seconds: 600.0
mode: prototype
pre_bootstrap_queue_timeout_seconds: 300
max_inbox_retry_attempts: 12
max_object_fetch_attempts: 3
object_fetch_timeout_seconds: 30.0
What is out of scope
This page covers the node configuration model only. The demo tooling reads a separate set of variables that are not node settings (CFG-04-007).
| Variable | Read by | Purpose |
|---|---|---|
VULTRON_SEED_CONFIG |
The demo seeding command, vultron-demo seed |
Path to the seed file that names the local actor and its peers |
VULTRON_ACTOR_ID, VULTRON_ACTOR_NAME, VULTRON_ACTOR_TYPE |
The demo seeding command | The bootstrap identity of the local actor |
VULTRON_API_BASE_URL |
The demo seeding command | The API server the seeding command writes the actor records to |
DEMO |
The Docker Compose demo runner | The demo scenario to run |
The Docker Compose files set node settings per container as environment variables; docker/README.md in the repository lists the values each container receives.
Further reading
- Run the Receive-Report Demo — starts a node with Docker Compose, or directly under
uvicornwithVULTRON_ACTOR__CASE_ACTOR_SERVICE_URLset. - Running the Multi-Actor Container Demos — runs one node per participant, each configured through its container's environment.