You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
MDK is under active development and is **not yet considered stable**.
14
14
15
-
Current release: [v0.2.0](https://github.com/tetherto/mdk/releases/tag/v0.2.0).
15
+
Current release: [v0.3.0](https://github.com/tetherto/mdk/releases/tag/v0.3.0).
16
16
17
17
## Table of Contents
18
18
@@ -130,10 +130,10 @@ leverage the packages provided for React (Vue, Svelte, and Web Components on the
130
130
131
131
## Releases
132
132
133
-
The latest development code is available on the [`main`](https://github.com/tetherto/mdk/tree/main) branch. MDK follows [Semantic Versioning 2.0.0](https://semver.org/): `0.y.z` versions are initial development (public API not stable until `1.0.0`).
133
+
The latest development code is available on the [`main`](https://github.com/tetherto/mdk/tree/main) branch. MDK follows [Semantic Versioning 2.0.0](https://semver.org/): `0.y.z` versions are initial development (public API not stable until `1.0.0`); `1.0.0` and above denote a stable public API.
The **App Node** is the mandatory gateway between the client-facing world (UI, AI agents) and the ORK kernel. It is a Fastify-based HTTP/WebSocket server that handles authentication, RBAC, fleet aggregation, and MCP endpoint exposure.
3
+
## Overview
4
4
5
-
UI and AI agents never connect to ORK directly. All traffic flows through the App Node.
The [plugin reference](../plugins/README.md) lists every default route, its method, auth requirement, and parameters.
47
+
48
+
## WebSocket subscriptions
55
49
56
50
Connect to `ws://localhost:3000/ws` for real-time telemetry subscriptions. Authentication is required in production mode.
57
51
58
52
## Configuration
59
53
60
-
Config files are written to `opts.root/config/facs/` by `startAppNode()`. Example files ship in `backend/core/app-node/config/facs/*.example`. Edit the generated files to persist your changes across restarts.
54
+
Config files are written to `opts.root/config/facs/` by `startAppNode()`. Example files ship in `backend/core/app-node/config/facs/*.example`.
55
+
Edit the generated files to persist your changes across restarts.
61
56
62
57
| File | Controls |
63
58
|------|---------|
@@ -68,26 +63,69 @@ Config files are written to `opts.root/config/facs/` by `startAppNode()`. Exampl
68
63
|`net.config.json`| IP assignment (DHCP facility) |
69
64
|`logging.config.json`| Log level, format |
70
65
71
-
## ORK Connection
66
+
## ORK connection
67
+
68
+
Two transports are available. Pass exactly one to `startAppNode()`:
69
+
70
+
**IPC (default — same host)**
72
71
73
-
The App Node connects to ORK over IPC (Unix socket) by default. The socket path is configured in `common.json`:
72
+
The App Node dials ORK over a Unix socket. The default socket path is `os.tmpdir()/mdk/ork.sock`.
74
73
75
74
```json
76
75
{ "orkIpc": "/tmp/mdk/ork.sock" }
77
76
```
78
77
79
-
Override via `startAppNode({ orkIpc: '/custom/path.sock' })` or pass `orkIpc: false` to disable the MDK client (useful when testing without a live ORK).
78
+
Override via `startAppNode({ orkIpc: '/custom/path.sock' })` or pass `orkIpc: false` to disable the MDK client
79
+
(useful when testing without a live ORK).
80
+
81
+
**HRPC (cross-host)**
82
+
83
+
When ORK runs on a separate host, pass the ORK HRPC gateway public key. This selects the HRPC transport and disables IPC automatically:
Obtain the ORK gateway key with `ork.getPublicKey().toString('hex')` on the host running ORK, then share it with the App Node host.
90
+
91
+
Pre v1.0, ORK's `auth.whitelist` defaults to empty (any HRPC caller is admitted). When an allowlist is configured, the App Node's DHT
92
+
public key must be added before the connection is accepted — see [ORK transports](../ork/README.md#transports).
80
93
81
-
## Security Model
94
+
## Security model
82
95
83
96
- UI and AI agents authenticate via **JWT Bearer tokens**
84
-
- ORK is protected by an HRPC **whitelist** — the App Node's public key must be in ORK's allowed list
85
-
- Once whitelisted, ORK trusts all messages from the App Node implicitly; user-level auth is the App Node's responsibility
86
-
- AI agents are treated as authenticated clients — they go through the same JWT/RBAC path as human API consumers
97
+
-**ORK connection security** depends on the transport:
98
+
-**IPC (same host, default)**: implicit trust — no allowlisting needed
99
+
-**HRPC (remote ORK)**: ORK maintains an HRPC firewall; the App Node's DHT public key must be in ORK's `auth.whitelist`.
100
+
See [ORK Transports](../ork/README.md#transports) and the [`auth-whitelist` example](../../../examples/backend/ork/auth-whitelist.js)
101
+
for the key exchange pattern.
102
+
- Once connected, ORK trusts all messages from the App Node implicitly; user-level auth is the App Node's responsibility
103
+
- AI agents are treated as authenticated clients, going through the same JWT/RBAC path as human API consumers
87
104
88
-
## Extending the App Node
105
+
## Extend the App Node
89
106
90
-
Add custom routes by passing `additionalRoutes` to `startAppNode()`:
107
+
### Plugin system (recommended)
108
+
109
+
Pass plugin directories via `extraPluginDirs` to load additional routes at startup alongside the default plugins:
110
+
111
+
```js
112
+
awaitstartAppNode({
113
+
ork,
114
+
extraPluginDirs: [
115
+
path.join(__dirname, 'plugins/my-metrics')
116
+
]
117
+
})
118
+
```
119
+
120
+
Plugins receive `(req, services)` in every controller, where `services.mdkClient` and `services.dataProxy` give access to ORK
121
+
and historical data without any protocol knowledge. The default plugins (`auth`, `telemetry`, `site-hashrate`) are loaded the same way.
122
+
123
+
The [plugin authoring guide](../../../docs/how-to/app-node/plugins.md) and the [plugin reference](../plugins/README.md) cover the full manifest schema, controller
124
+
contract, services bag, and loader errors.
125
+
126
+
### Raw Fastify routes
127
+
128
+
For one-off handlers that do not need the plugin manifest format, pass `additionalRoutes` directly:
91
129
92
130
```js
93
131
awaitstartAppNode({
@@ -102,28 +140,36 @@ await startAppNode({
102
140
})
103
141
```
104
142
105
-
## Running Standalone
143
+
These are registered as plain Fastify routes — no `services` injection, no manifest validation, no auth wiring.
0 commit comments