Node Startup
Startup gating, async activity loading, and identity awareness
Node Startup
How OctoMY™ nodes decide what to show after launch.
Key Insight
The startup system uses a convergence gate pattern: the splash screen stays up until all required preconditions are met, then the node makes a single, correct decision about what to display. This avoids race conditions between asynchronous service activation and UI readiness.
Overview
After a node's services are configured (see Node Lifecycle), the window needs to decide what to show the user. For Agent and Remote, this means choosing between the unboxing wizard (if the node has no cryptographic identity) or the main UI. For Hub, identity is optional and never blocks startup.
This decision cannot be made immediately because the KeyStore loads asynchronously during service activation. The startup system coordinates these asynchronous events using a StartupGate.
StartupGate
The StartupGate is a lightweight convergence mechanism that tracks named preconditions and fires a signal when all are satisfied.
StartupGate
├── addCondition("activities_loaded")
├── addCondition("keystore_ready")
│
├── satisfy("activities_loaded") ← ActivityLoader finishes
├── satisfy("keystore_ready") ← KeyStore emits keystoreReady
│
└── allMet() signal fires ← Both done, proceed
Each node type registers different conditions:
| Node Type | Conditions | On allMet() |
|---|---|---|
| Agent | activities_loaded, keystore_ready |
Wizard-or-main-UI decision, then complete splash |
| Remote | activities_loaded, keystore_ready |
Wizard-or-main-UI decision, then complete splash |
| Hub | activities_loaded |
Show main menu, then complete splash |
| MockNode | (none, synchronous) | Direct splash completion |
Three startup strategies
Strategy A: Identity-Enforced (Agent, Remote)
Agent and Remote are mobile-focused nodes that are fundamentally useless without a cryptographic identity. The unboxing wizard is enforced at startup.
Sequence:
- Activities load asynchronously via
ActivityLoader - KeyStore activates and emits
keystoreReady StartupGate::allMet()fires- Check
keyStore()->localKey():- Non-null: Node is delivered, show main UI
- Null: Node needs identity, show unboxing wizard
- Complete splash
The splash animation stays smooth throughout because activity loading is non-blocking (one activity instantiated per event loop cycle).
Strategy B: Identity-Optional (Hub)
Hub is desktop-focused. Most features (constellation management, file management, automation) work without an identity. Only comms and pairing require one.
Sequence:
- Activities load asynchronously via
ActivityLoader StartupGate::allMet()fires (no KeyStore wait)- Show
HubMainMenuimmediately - Complete splash
Identity awareness is provided by the IdentityStatusWidget in the navigation header, so the user can set up identity at their discretion without being blocked at startup.
Strategy C: Test Tool (MockNode)
MockNode is a testing tool. Activities load synchronously (the small count makes async unnecessary). A status label in the header shows identity state, updating dynamically as the KeyStore loads.
ActivityLoader
All native node windows (Agent, Remote, Hub) use the ActivityLoader for non-blocking activity instantiation.
The loader processes activities one per event loop cycle, keeping the UI responsive during startup. Activities can be configured with:
- Priority ordering: Critical activities (main UI, wizard) load first
- Animation breaks: Pause between groups for splash animation
- Lazy loading: Non-essential activities defer until after startup
When all activities are instantiated, the loader emits finished, which satisfies the "activities_loaded" gate condition.
IdentityStatusWidget
A compact widget in Hub's navigation header that shows the current identity state:
[Back] [Title] [Entropy] [Batch] [Lanyard: hive · sentient · node] [OPAL] [Menu]
(Post-makeover layout. The pre-makeover [IdentityStatus] widget was folded into the Lanyard; the standalone [Debugger] and [Screenshot] slots moved into the Menu button's right-click context menu — see the internal Activity Header Makeover spec, §MC. [OPAL] is the bare-glyph articulated AI-status button — see §OB.)
States
| State | Appearance | Click Action |
|---|---|---|
| Loading | Key icon, "Identity..." | No action |
| Not Delivered | Warning icon, "Set up identity", amber highlight | Navigate to identity menu |
| Delivered | Identicon thumbnail, truncated node ID | Navigate to identity details |
The widget connects to KeyStore::keystoreReady and transitions automatically as the KeyStore loads. For delivered nodes, it renders an identicon from the node's PortableNodeID and shows a truncated hex ID (e.g., a3f8...c2e1).
Visibility
- Hub: Always visible (identity is optional but surfaced)
- Agent/Remote: Hidden (identity is enforced at startup via the wizard)
- MockNode: Uses a simpler
QLabelstatus indicator in its own header
Startup timeline
Time →
appConfigure() nodeWindowConfigure() appActivate()
│ │ │
│ Configure services │ Start splash │ Services activate
│ (KeyStore, Comms, │ Register gate conditions │ asynchronously
│ AddressBook, etc.) │ Start ActivityLoader │
│ │ │
▼ ▼ ▼
KeyStore loads
│
ActivityLoader finishes │
│ │
▼ ▼
satisfy("activities") satisfy("keystore")
│ │
└────────┬────────────┘
│
allMet() fires
│
▼
Show correct UI
Complete splash
MockNode identity indicator
MockNode windows display a styled label in the header bar showing identity state. The label updates dynamically when:
- The KeyStore finishes loading (initial state detection)
- Delivery completes (transitions from "No Identity" to showing the node ID)
- Factory reset occurs (transitions back to "No Identity")
This provides quick visual feedback during testing without the complexity of the full IdentityStatusWidget.