173 lines
15 KiB
Markdown
173 lines
15 KiB
Markdown
# nenjim-hub-configuration Specification
|
|
|
|
## Purpose
|
|
|
|
Defines the mandatory deployment configuration that selects which modern Nenjim processes the Hub constructs and starts, while preserving explicit order and fail-fast lifecycle semantics.
|
|
|
|
## Requirements
|
|
|
|
### Requirement: Hub startup requires one fixed runtime configuration
|
|
The reference Hub SHALL read only `conf/NenjimHub.conf` and SHALL complete all configuration parsing and validation before starting Registry or any other process. The path SHALL not be configurable through `Main`, command-line arguments, or the public `NenjimHub` API. A missing, unreadable, or non-regular runtime file SHALL fail Hub startup clearly and identify the configured path. The Hub SHALL not read, copy, generate, or fall back to `conf/NenjimHub.conf.example`, and SHALL not fall back to a hardcoded startup list.
|
|
|
|
#### Scenario: Runtime configuration is valid
|
|
- **WHEN** `conf/NenjimHub.conf` is a readable regular file containing a valid format 1 configuration
|
|
- **THEN** the Hub derives its complete requested process order from that file before starting Registry
|
|
|
|
#### Scenario: Runtime configuration cannot be read
|
|
- **WHEN** `conf/NenjimHub.conf` is missing, unreadable, or not a regular file
|
|
- **THEN** startup fails with a diagnostic identifying `conf/NenjimHub.conf` before any process starts
|
|
|
|
#### Scenario: Only the example exists
|
|
- **WHEN** `conf/NenjimHub.conf` is absent but `conf/NenjimHub.conf.example` exists
|
|
- **THEN** startup fails without reading, copying, or using the example and without starting a hardcoded fallback set
|
|
|
|
### Requirement: Format 1 has one exact ordered AUTO_START section
|
|
The first actual configuration entry SHALL be exactly `FORMAT_VERSION=1`, after optional leading blank lines and full-line comments. Version 1 SHALL be the only supported version; a missing, malformed, duplicate, version 2, or otherwise unsupported declaration SHALL fail. The next actual entry SHALL be exactly one `[AUTO_START]` header, optionally followed only by a trailing `#` comment. Unknown, malformed, repeated, valued, or out-of-order sections and entries before `[AUTO_START]` SHALL fail.
|
|
|
|
Outside `[AUTO_START]`, leading and trailing whitespace SHALL be ignored, a line whose trimmed content begins with `#` SHALL be a full-line comment, and `#` after actual content SHALL begin a trailing comment. Inside `[AUTO_START]`, surrounding whitespace around a process ID SHALL be ignored; full-line and trailing comments SHALL be ignored; comment-only lines SHALL not terminate the section; and the first whitespace-only line or end of file SHALL terminate it. After termination, only blank lines and comments SHALL be accepted. Format 1 SHALL provide no quoting or escaping for `#`.
|
|
|
|
#### Scenario: Leading comments and trailing comments are accepted
|
|
- **WHEN** blank lines or full-line comments precede `FORMAT_VERSION=1`, and the version, section header, or process entries contain trailing `#` comments
|
|
- **THEN** comment text and permitted surrounding whitespace are ignored while the actual entries are parsed normally
|
|
|
|
#### Scenario: Comment inside AUTO_START does not terminate it
|
|
- **WHEN** a comment-only line appears between two process IDs in `[AUTO_START]`
|
|
- **THEN** both process IDs remain part of the ordered section
|
|
|
|
#### Scenario: Empty line terminates AUTO_START
|
|
- **WHEN** a whitespace-only line appears after at least one `[AUTO_START]` entry
|
|
- **THEN** the section terminates at that line and later actual content fails as unexpected content
|
|
|
|
#### Scenario: End of file terminates AUTO_START
|
|
- **WHEN** the final process ID is immediately followed by end of file
|
|
- **THEN** the section terminates successfully at end of file
|
|
|
|
#### Scenario: Version declaration is invalid
|
|
- **WHEN** the version is absent, malformed, duplicated, not the first actual entry, or has a value other than `1`
|
|
- **THEN** configuration validation fails before any process starts and identifies the path, relevant line and reason
|
|
|
|
#### Scenario: Section structure is invalid
|
|
- **WHEN** `[AUTO_START]` is absent, duplicated, misspelled, has a value or non-comment trailing token, follows another actual entry, or is replaced by an unknown section
|
|
- **THEN** configuration validation fails before any process starts and identifies the path, relevant line, offending content and reason
|
|
|
|
### Requirement: The complete requested process plan is validated before startup
|
|
Every active `[AUTO_START]` line SHALL be parsed through the canonical `NenjimComponentId` rules and retained in source order with its line location. Before Registry starts, validation SHALL reject invalid ID syntax, duplicate IDs, unknown IDs, passive-only component IDs, and IDs the reference Hub cannot construct as canonical `NenjimProcess` objects. The section SHALL contain Registry exactly once at position one and Journal exactly once at position two. Applicable failures SHALL identify `conf/NenjimHub.conf`, the relevant line, offending value, and reason.
|
|
|
|
#### Scenario: Process ID is malformed
|
|
- **WHEN** an active section line is not a valid `NenjimComponentId`
|
|
- **THEN** validation fails before Registry startup and identifies the path, line, offending value and component-ID reason
|
|
|
|
#### Scenario: Process ID is duplicated
|
|
- **WHEN** the same canonical process ID appears more than once
|
|
- **THEN** validation fails before Registry startup and identifies the duplicate value and line
|
|
|
|
#### Scenario: ID is not constructible as a process
|
|
- **WHEN** an entry is unknown, identifies only a passive component, or is not in the Hub's modern process-construction catalogue
|
|
- **THEN** validation fails before Registry startup rather than constructing or starting any process
|
|
|
|
#### Scenario: Bootstrap entries are not first and second
|
|
- **WHEN** Registry is absent or not first, or Journal is absent or not second
|
|
- **THEN** validation fails before Registry startup and identifies the required placement
|
|
|
|
### Requirement: Registry bootstraps eager passive composition
|
|
After validating the entire plan, the Hub SHALL construct the configured Registry subsystem, start Registry, register its service and process object as `nenjim.registry.service`, and record that ID only after successful startup. The Hub SHALL then eagerly construct and register the existing shared passive component graph. Dedicated liquidity deployment configuration, wallet signer, Jupiter swap service and direct Raydium service SHALL instead be constructed and registered only when the configured `evelyn.liquidity.prod` entry is reached. This passive phase SHALL not construct any canonical `NenjimProcess`, start background workers, initialize JavaFX, add startup IDs, infer process dependencies, or implicitly create an omitted process. Plain internal dependencies that are not `NenjimComponent` objects MAY be constructed as part of passive composition.
|
|
|
|
#### Scenario: Registry surrounds passive composition
|
|
- **WHEN** a valid Hub startup begins
|
|
- **THEN** Registry starts, is registered, and is recorded before the existing shared passive component graph is constructed and registered
|
|
|
|
#### Scenario: Passive composition completes
|
|
- **WHEN** Registry bootstrap succeeds
|
|
- **THEN** all existing shared non-process building blocks, adapters, and services are constructed and registered without starting a process
|
|
|
|
#### Scenario: Passive construction fails
|
|
- **WHEN** any passive component cannot be constructed or registered
|
|
- **THEN** startup stops immediately with Registry remaining recorded and no configured process after Registry constructed or started
|
|
|
|
#### Scenario: Liquidity is omitted
|
|
- **WHEN** the plan omits `evelyn.liquidity.prod`
|
|
- **THEN** its deployment configuration, dedicated signer/wallet, Jupiter service and direct Raydium service are neither loaded nor constructed nor registered
|
|
|
|
### Requirement: Selected processes are constructed and started lazily in exact order
|
|
The Hub SHALL support the modern process IDs `nenjim.registry.service`, `nenjim.journal.service`, `assetaz.ticker.default`, `jupiter-perps-alarm.default`, `evelyn.status.prod`, `evelyn.status.test`, `evelyn.iou-burner.prod`, `evelyn.liquidity.prod`, `evelyn.perps.default`, `nenjim.javafx-runtime.service`, `evelyn.mission-control.default`, and `nenjim.process-manager.default` through implementation-only construction capability that creates no process instance during validation. After passive composition, the Hub SHALL visit every configured entry after Registry in declared order, beginning with Journal. At each entry it SHALL construct only that process and any explicitly composed process-specific passive dependencies or administration view, register the process under the exact configured ID, resolve it through the canonical `NenjimProcess` contract where applicable, call `start()`, and record the ID only after successful return.
|
|
|
|
The production IOU burner SHALL receive the already constructed Production Evelyn status service, and SHALL require both Ticker and `evelyn.status.prod` to precede `evelyn.iou-burner.prod`. EMC SHALL receive the already started `evelyn.perps.default` service, which SHALL precede EMC in the deployment autostart list. The configuration SHALL be the complete manually ordered process dependency closure. The Hub SHALL not discover, insert, recursively construct, reorder, or automatically start dependencies. A process omitted from `[AUTO_START]` SHALL not be constructed, registered, started, or recorded, even when its implementation is available. Legacy process prototypes outside the modern Hub graph SHALL not be selectable.
|
|
|
|
#### Scenario: Configured process starts successfully
|
|
- **WHEN** a configured process entry is reached and its dependencies are already available
|
|
- **THEN** that process is constructed, registered, started, and recorded before the next entry is reached
|
|
|
|
#### Scenario: Process is omitted
|
|
- **WHEN** a known process ID does not appear in `[AUTO_START]`
|
|
- **THEN** no instance of that process is constructed or registered and its lifecycle is never started or recorded
|
|
|
|
#### Scenario: Jupiter Perps Alarm is selected
|
|
- **WHEN** `jupiter-perps-alarm.default` is explicitly listed after its required predecessors
|
|
- **THEN** the otherwise inactive modern alarm process is constructed, registered, started and recorded at that exact position
|
|
|
|
#### Scenario: Dependency order is invalid
|
|
- **WHEN** a selected process is reached before a process dependency required by its current constructor or startup behavior
|
|
- **THEN** construction or startup fails clearly without implicit dependency construction, repair, or reordering
|
|
|
|
#### Scenario: JavaFX processes are omitted
|
|
- **WHEN** a valid headless plan omits `nenjim.javafx-runtime.service`, `evelyn.mission-control.default`, and `nenjim.process-manager.default`
|
|
- **THEN** none of those objects is constructed or registered and the JavaFX toolkit remains uninitialized by the Hub
|
|
|
|
#### Scenario: Renamed status services retain dependency wiring
|
|
- **WHEN** `evelyn.status.prod` and `evelyn.status.test` are listed after Ticker and before Mission Control
|
|
- **THEN** the Hub constructs separate Production/Test status services, registers the renamed IDs, and injects the corresponding typed service views into Mission Control in the configured order
|
|
|
|
#### Scenario: Deployment still contains an old status ID
|
|
- **WHEN** a private deployment configuration contains `evelyn.service.prod` or `evelyn.service.test`
|
|
- **THEN** validation rejects the unknown ID before startup; deployment migration replaces only that ID with `evelyn.status.prod` or `evelyn.status.test`, preserving selection and order
|
|
|
|
#### Scenario: Liquidity is explicitly selected
|
|
- **WHEN** `evelyn.liquidity.prod` is reached in a valid startup plan
|
|
- **THEN** the Hub loads its runtime configuration, binds the dedicated signer/wallet and Jupiter service to each other, constructs direct Raydium access and registers/starts the liquidity process without inserting a Ticker or status dependency or reordering the plan
|
|
|
|
#### Scenario: Production burner has its reference-price dependency
|
|
- **WHEN** `evelyn.iou-burner.prod` is reached after Ticker and `evelyn.status.prod`
|
|
- **THEN** the Hub injects the corresponding Production status service for buyback price decisions
|
|
|
|
#### Scenario: Production burner precedes its status dependency
|
|
- **WHEN** the burner is reached without a previously constructed Production status service
|
|
- **THEN** construction fails clearly without creating or starting the omitted dependency or the burner
|
|
|
|
#### Scenario: EMC has its Perps dependency
|
|
- **WHEN** `evelyn.perps.default` appears before EMC in the deployment's ordered autostart list
|
|
- **THEN** the Hub registers and starts that service and injects its service view into EMC
|
|
|
|
#### Scenario: EMC precedes Perps
|
|
- **WHEN** EMC is selected without an earlier Perps process
|
|
- **THEN** construction fails clearly without inserting or starting that dependency
|
|
|
|
### Requirement: Configured startup is fail-fast and reports actual milestones
|
|
Registry and every selected process SHALL be registered before its `start()` call and appended to the Hub's immutable ordered startup snapshot only after `start()` returns successfully. Construction failure SHALL leave the selected process unregistered. Registration or startup failure SHALL stop the plan before any later entry is constructed or started; a startup failure MAY leave that process registered but SHALL not record it. Earlier successful processes SHALL remain in snapshots, no rollback or retry SHALL occur, and the Hub SHALL announce its existing online point and enter its blocking runtime wait only after every configured process succeeds.
|
|
|
|
#### Scenario: Selected construction fails
|
|
- **WHEN** construction of the current selected process throws
|
|
- **THEN** the process is not registered or recorded, no later process is constructed, and the Hub does not announce online or enter its final wait
|
|
|
|
#### Scenario: Selected registration fails
|
|
- **WHEN** registration of the constructed current process throws
|
|
- **THEN** the process is not started or recorded, no later process is constructed, and no rollback is attempted
|
|
|
|
#### Scenario: Selected startup fails
|
|
- **WHEN** the current process's `start()` throws
|
|
- **THEN** it remains unrecorded, no later process is constructed or started, earlier successful IDs remain visible, and no rollback is attempted
|
|
|
|
#### Scenario: Configured startup completes
|
|
- **WHEN** all configured process starts return successfully
|
|
- **THEN** the startup snapshot has the exact configured order, the online point is announced, and the Hub enters its existing blocking wait
|
|
|
|
### Requirement: The version-controlled example is a copy-only template
|
|
The repository SHALL contain `conf/NenjimHub.conf.example` as a documented format 1 copy-only template with only the mandatory Registry and Journal entries active. It SHALL contain no optional deployment-specific process IDs. Its comments SHALL state that the file must be copied to `conf/NenjimHub.conf` before use, Registry and Journal are mandatory, order is preserved, and process dependencies must be listed manually before their consumers. Documentation SHALL show the same minimal bootstrap as a headless example and SHALL describe recursive dependency construction as future work rather than implemented behavior.
|
|
|
|
#### Scenario: Example provides a generic minimal bootstrap
|
|
- **WHEN** the example's uncommented process IDs are read in order
|
|
- **THEN** they are only Registry and Journal, with no optional deployment-specific process ID present
|
|
|
|
#### Scenario: Operator uses the minimal headless example
|
|
- **WHEN** the documented headless configuration is copied to the runtime path
|
|
- **THEN** it selects only Registry and Journal and leaves every optional process for the operator to add explicitly
|