A node's worker label is worker, so a device is only a paired one

- NodeDef `device`/`device_policy` become `worker`/`worker_policy`, the
  issue `ignored_device` becomes `ignored_worker`, and the SDK's `@node`
  takes `worker=` and `worker_policy=`
- FlowStore._migrate renames the keys in published and draft documents
  once, bumping their version; a queued run's `needs` reads the old key
- placement passes the label as `label`, client regenerated
- docs: worker placement wording, MCP issuer without DOMAIN, device rows in
  the CLI data directory and the API table, device links in compose comments

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Melvin Strobl
2026-10-16 16:56:05 +02:00
co-authored by Claude Opus 5.5
parent f8011d2a8a
commit a9d453c9d9
40 changed files with 215 additions and 178 deletions
+2 -2
View File
@@ -18,8 +18,8 @@ issuer of the client's tokens.
The client registers, opens browser authorization, and receives an OAuth
token after you approve access. The issuer and browser redirects use
`DOMAIN`, `ENVIRONMENT`, and `FRONTEND_HOST`, so configure those for the
addresses your client and browser can reach.
`FRONTEND_HOST` and `ENVIRONMENT`, so configure those for the addresses your
client and browser can reach.
Manage registered clients under **Admin → Agents**. Revoking a client
invalidates its access. MCP uses a separate signing key at
+1
View File
@@ -195,6 +195,7 @@ on its own, so this is for reclaiming space sooner.
| `POST` | `/devices/pair` | start device pairing, optionally with `{name, board, firmware}`; unauthenticated |
| `GET` | `/devices/pair/{code}` | poll pairing with its `secret`; answers `device` (and `panel` for older firmware); unauthenticated |
| `GET` | `/devices/pending` | devices waiting for a code, as they describe themselves |
| `GET` | `/devices/pair/{code}/device` | what is waiting on a code, before it is approved |
| `POST` | `/devices/{id}/pair` | adopt by `{code}`, or by `{request}` from the pending list for a request from your network |
| `POST` | `/devices/{id}/unpair` | revoke the device credential |
+2 -1
View File
@@ -340,7 +340,8 @@ The main files and directories are:
|---|---|
| `client.json` | Local API URL and token |
| `fluksio.db` | SQLite database: accounts, runs, metrics and operations history |
| `flows/` | Git repository of flows, node sources, dashboards and module requirements |
| `flows/` | Git repository of flows, node sources, dashboards, devices (`_devices/`) and module requirements |
| `devices.json` | Device credential nonces, outside the flow repository |
| `artifacts/` | Files stored by content digest |
| `user-venv/` | Managed node environment, when used |
| `secrets.enc` | Encrypted credentials, outside the flow repository |
+2 -2
View File
@@ -324,10 +324,10 @@ waiting for that deadline.
## Running a node somewhere else
Set a device label to select an attached worker:
Set a worker label to select an attached worker:
```json
{"id": "train", "device": "gpu", "device_policy": "require", "timeout": 7200}
{"id": "train", "worker": "gpu", "worker_policy": "require", "timeout": 7200}
```
`require` is the default and waits for a worker with that label. `prefer` uses
+4 -4
View File
@@ -76,16 +76,16 @@ Set these fields on a node through `PUT /api/v1/flows/{name}`:
```json
{
"id": "train",
"device": "gpu",
"device_policy": "require",
"worker": "gpu",
"worker_policy": "require",
"timeout": 7200
}
```
This is a node fragment; keep the node's other fields and the rest of the flow
when updating it. `device` and `device_policy` are not in the node panel yet.
when updating it. `worker` and `worker_policy` are not in the node panel yet.
| `device_policy` | If no matching worker is attached |
| `worker_policy` | If no matching worker is attached |
|---|---|
| `require` (default) | queues until a matching worker is available |
| `prefer` | falls back to the engine |
+1 -1
View File
@@ -137,7 +137,7 @@ The canvas reports issues on the affected nodes:
| `missing_source` | a Function node has no saved code |
| `node_error` | code or configuration could not load |
| `unauthenticated_hook` | a webhook or served websocket has no shared secret; advisory |
| `ignored_device` | a node other than a Function node names a device, which nothing reads; advisory |
| `ignored_worker` | a node other than a Function node names a worker, which nothing reads; advisory |
| `unknown_device` | a Device node names no device, or one that does not exist |
| `device_port` | a device port is wired in two places, or against the device's report the wrong way or type; a port the report does not list is advisory |
| `node_unhealthy` | a loaded node reports a runtime problem, such as a lost connection, or a device being offline |
+1 -1
View File
@@ -157,7 +157,7 @@ artifact and rebuild the object in the next node.
## Running a node somewhere else
Attach a [remote worker](../code/workers.md) to the engine and declare the
worker's label as the node's `device`. `device_policy="require"` waits for
worker's label as the node's `worker`. `worker_policy="require"` waits for
that label; `"prefer"` uses the local engine when none is attached.
The selected machine needs your imported packages. Code-defined flows also
+3 -3
View File
@@ -322,10 +322,10 @@ face, and the editor marks it **Poor fit for round**.
| Gesture | Effect |
|---|---|
| Swipe left / right | next / previous face of this dashboard; stops at either end |
| Swipe up / down | next / previous dashboard of the panel (`/panel/{id}` only); stops at either end |
| Swipe up / down | next / previous dashboard of the device (`/panel/{id}` only); stops at either end |
| Page dot | that face |
| PageDown / PageUp | next / previous face |
| Shift+PageDown / Shift+PageUp | next / previous dashboard of the panel |
| Shift+PageDown / Shift+PageUp | next / previous dashboard of the device |
| Arrow keys | turn the ring, not the page |
A swipe carries the page with the finger ([Swiping](#swiping)); a drag that
@@ -423,7 +423,7 @@ angle, which is what the browser's reveal amounts to.
### Swiping
Faces are swiped sideways and a panel's dashboards up and down, with the page
Faces are swiped sideways and a device's dashboards up and down, with the page
under the finger, as a tile view moves.
| Part | Value |
+1 -1
View File
@@ -68,7 +68,7 @@ yielding regularly can run longer than its timeout. Empty or `0` means no
limit, the default.
**Resources** selects a shared worker pool, a named flavor or custom CPU,
memory and GPU requirements. Placement by `device` and `device_policy` is
memory and GPU requirements. Placement by `worker` and `worker_policy` is
configured through the API or flow JSON; see [Remote workers](../code/workers.md).
### Code and reuse
+1 -1
View File
@@ -92,7 +92,7 @@ proxy on that route must support WebSockets.
the portal to be online. It also deletes the users the portal let in; the
account that enrolled and every superuser stay.
- To replace the pairing, use **Connect with a new code**. Remote users and
panels may need to pair again.
devices paired through the portal may need to pair again.
If the instance is removed at the portal, or its code is renewed there, the
status reads **Removed at the portal** and the instance stops dialling. Connect
+1 -1
View File
@@ -31,7 +31,7 @@
- [The fluksio command](/code/cli/): serve, enroll, worker, and the data directory
- [Writing node code](/code/nodes/): process(), generators, fluksio.emit, artifacts
- [The HTTP API](/code/api/): auth, flows, messages, runs, observability, websocket
- [Remote workers](/code/workers/): fluksio-worker, device labels, artifacts across hosts
- [Remote workers](/code/workers/): fluksio-worker, worker labels, artifacts across hosts
- [Agents over MCP](/code/agents/): the tool list and the security model
- [Writing a connector](/code/connectors/): packaging a device integration as a node type