135 lines
3.5 KiB
Markdown
135 lines
3.5 KiB
Markdown
# Yonexus.Client
|
|
|
|
Yonexus.Client is the follower-side plugin for a Yonexus network.
|
|
|
|
It runs on non-central OpenClaw instances and is responsible for:
|
|
|
|
- connecting outbound to `Yonexus.Server`
|
|
- managing local identifier + trust material
|
|
- generating a local Ed25519 keypair on first run
|
|
- completing out-of-band pairing
|
|
- authenticating on reconnect with signed proof
|
|
- sending periodic heartbeats
|
|
- dispatching inbound rule messages to locally registered handlers
|
|
|
|
## Status
|
|
|
|
Current state: **scaffold + core runtime MVP**
|
|
|
|
Implemented in this repository today:
|
|
|
|
- config validation
|
|
- local state store for identifier / keypair / secret
|
|
- automatic first-run keypair generation
|
|
- WebSocket client transport with reconnect backoff
|
|
- hello / hello_ack handling
|
|
- pairing pending flow + pairing code submission
|
|
- auth_request generation and auth state transitions
|
|
- heartbeat loop
|
|
- rule registry + send-to-server APIs
|
|
|
|
Still pending before production use:
|
|
|
|
- automated Client unit/integration tests
|
|
- richer operator UX for entering pairing codes
|
|
- final OpenClaw lifecycle hook integration
|
|
- deployment/troubleshooting docs specific to follower instances
|
|
|
|
## Configuration
|
|
|
|
Required config shape:
|
|
|
|
```json
|
|
{
|
|
"mainHost": "wss://example.com/yonexus",
|
|
"identifier": "client-a",
|
|
"notifyBotToken": "<discord-bot-token>",
|
|
"adminUserId": "123456789012345678"
|
|
}
|
|
```
|
|
|
|
### Field notes
|
|
|
|
- `mainHost`: WebSocket URL of the Yonexus server (`ws://` or `wss://`)
|
|
- `identifier`: unique client identity inside the Yonexus network
|
|
- `notifyBotToken`: currently kept aligned with system-level config expectations
|
|
- `adminUserId`: admin reference used by the broader Yonexus pairing model
|
|
|
|
## Runtime Overview
|
|
|
|
Startup flow:
|
|
|
|
1. validate config
|
|
2. load local state
|
|
3. generate keypair if missing
|
|
4. connect to `mainHost`
|
|
5. send `hello`
|
|
6. continue into pairing or auth depending on server response
|
|
|
|
Authentication flow:
|
|
|
|
1. receive `hello_ack(auth_required)` or `pair_success`
|
|
2. build proof from `secret + nonce + timestamp` using canonical JSON bytes
|
|
3. sign with local Ed25519 private key
|
|
4. send `auth_request`
|
|
5. on success, enter authenticated state and start heartbeat loop
|
|
|
|
Pairing flow:
|
|
|
|
1. receive `pair_request` metadata from server
|
|
2. obtain pairing code from the human-admin out-of-band channel
|
|
3. submit pairing code through `submitPairingCode()`
|
|
4. persist returned secret after `pair_success`
|
|
|
|
## Public API Surface
|
|
|
|
Exported runtime helpers currently include:
|
|
|
|
```ts
|
|
sendMessageToServer(message: string): Promise<boolean>
|
|
sendRuleMessage(ruleIdentifier: string, content: string): Promise<boolean>
|
|
registerRule(rule: string, processor: (message: string) => unknown): void
|
|
submitPairingCode(pairingCode: string): Promise<boolean>
|
|
```
|
|
|
|
Rules:
|
|
|
|
- application messages must use `${rule_identifier}::${message_content}`
|
|
- `builtin` is reserved and cannot be registered as an application rule
|
|
|
|
## Local State
|
|
|
|
The client persists at least:
|
|
|
|
- `identifier`
|
|
- `privateKey`
|
|
- `publicKey`
|
|
- `secret`
|
|
- key/auth/pair timestamps
|
|
|
|
This is enough to survive restarts and perform authenticated reconnects.
|
|
|
|
## Development
|
|
|
|
Install dependencies and run type checks:
|
|
|
|
```bash
|
|
npm install
|
|
npm run check
|
|
```
|
|
|
|
## Limitations
|
|
|
|
Current known limitations:
|
|
|
|
- no polished end-user pairing code entry UX yet
|
|
- no client unit/integration test suite yet
|
|
- no offline buffering/queueing
|
|
- no end-to-end encrypted payload channel beyond current pairing/auth model
|
|
|
|
## Related Repos
|
|
|
|
- Umbrella: `../`
|
|
- Shared protocol: `../Yonexus.Protocol`
|
|
- Server plugin: `../Yonexus.Server`
|