Cluster API
Source: daemon/proto/hostcraft/v1/cluster.proto
ClusterService
Section titled “ClusterService”ClusterService manages a panel node's agents: nodes, enrolment tokens, decommission and drain, account moves, topology and the event feed. REST: /api/v1/cluster. Agent enrolment itself (POST /api/v1/cluster/enrol, authenticated by the one-time token) is REST only; agents and the panel talk mTLS over NATS, not this API.
| Method | REST route | Permission | Streaming |
|---|---|---|---|
ListNodes |
GET /api/v1/cluster/nodes |
ClusterRead |
unary |
GetNode |
GET /api/v1/cluster/nodes/{id} |
ClusterRead |
unary |
DecommissionNode |
POST /api/v1/cluster/nodes/{id}/decommission |
ClusterDecommissionNode |
unary |
TriggerHealthCheck |
POST /api/v1/cluster/nodes/{id}/health-check |
ClusterWrite |
unary |
RotateNodeCert |
POST /api/v1/cluster/nodes/{id}/rotate-cert |
ClusterWrite |
unary |
CreateEnrolmentToken |
POST /api/v1/cluster/enrolment-tokens |
ClusterTokenCreate |
unary |
ListEnrolmentTokens |
GET /api/v1/cluster/enrolment-tokens |
ClusterRead |
unary |
RevokeEnrolmentToken |
DELETE /api/v1/cluster/enrolment-tokens/{token} |
ClusterTokenRevoke |
unary |
GetTopology |
GET /api/v1/cluster/topology |
ClusterRead |
unary |
MoveAccount |
POST /api/v1/cluster/moves |
ClusterMoveAccount |
unary |
ListMoves |
GET /api/v1/cluster/moves |
ClusterRead |
unary |
GetMove |
GET /api/v1/cluster/moves/{id} |
ClusterRead |
unary |
StreamClusterEvents |
native | ClusterRead |
server |
ListNodes
Section titled “ListNodes”/hostcraft.v1.ClusterService/ListNodes
- Request: ListNodesRequest
- Response: ListNodesResponse
GetNode
Section titled “GetNode”/hostcraft.v1.ClusterService/GetNode
- Request: GetNodeRequest
- Response: ClusterNode
DecommissionNode
Section titled “DecommissionNode”DecommissionNode removes an agent. With drain set, every account on the node is first moved (to target_node, or the least loaded agent) by the cluster.drain saga; force skips the drain safety checks.
/hostcraft.v1.ClusterService/DecommissionNode
- Request: DecommissionNodeRequest
- Response: WorkflowAccepted
TriggerHealthCheck
Section titled “TriggerHealthCheck”/hostcraft.v1.ClusterService/TriggerHealthCheck
- Request: TriggerHealthCheckRequest
- Response: ClusterNode
RotateNodeCert
Section titled “RotateNodeCert”/hostcraft.v1.ClusterService/RotateNodeCert
- Request: RotateNodeCertRequest
- Response: WorkflowAccepted
CreateEnrolmentToken
Section titled “CreateEnrolmentToken”/hostcraft.v1.ClusterService/CreateEnrolmentToken
- Request: CreateEnrolmentTokenRequest
- Response: EnrolmentToken
ListEnrolmentTokens
Section titled “ListEnrolmentTokens”/hostcraft.v1.ClusterService/ListEnrolmentTokens
- Request: ListEnrolmentTokensRequest
- Response: ListEnrolmentTokensResponse
RevokeEnrolmentToken
Section titled “RevokeEnrolmentToken”/hostcraft.v1.ClusterService/RevokeEnrolmentToken
- Request: RevokeEnrolmentTokenRequest
- Response: Empty
GetTopology
Section titled “GetTopology”/hostcraft.v1.ClusterService/GetTopology
- Request: GetTopologyRequest
- Response: ClusterTopology
MoveAccount
Section titled “MoveAccount”MoveAccount migrates one account to another node (files, databases, mail, config) through the cluster.move saga.
/hostcraft.v1.ClusterService/MoveAccount
- Request: MoveAccountRequest
- Response: MoveAccountResponse
ListMoves
Section titled “ListMoves”/hostcraft.v1.ClusterService/ListMoves
- Request: ListMovesRequest
- Response: ListMovesResponse
GetMove
Section titled “GetMove”/hostcraft.v1.ClusterService/GetMove
- Request: GetMoveRequest
- Response: AccountMove
StreamClusterEvents
Section titled “StreamClusterEvents”StreamClusterEvents streams node joined/left/health events until the client cancels. REST equivalent: GET /api/v1/cluster/events (SSE).
/hostcraft.v1.ClusterService/StreamClusterEvents
- Request: StreamClusterEventsRequest
- Response: ClusterEvent
Messages
Section titled “Messages”AccountMove
Section titled “AccountMove”| Field | Type | Number | Description |
|---|---|---|---|
id |
string |
1 | - |
account_id |
string |
2 | - |
source_node |
string |
3 | - |
target_node |
string |
4 | - |
drain_id |
string |
5 | - |
workflow_id |
string |
6 | - |
status |
string |
7 | - |
step |
string |
8 | - |
bytes_total |
int64 |
9 | - |
bytes_done |
int64 |
10 | - |
error |
string |
11 | - |
warnings |
string |
12 | - |
created_at |
google.protobuf.Timestamp |
13 | - |
updated_at |
google.protobuf.Timestamp |
14 | - |
ClusterEvent
Section titled “ClusterEvent”| Field | Type | Number | Description |
|---|---|---|---|
kind |
string |
1 | - |
node_id |
string |
2 | - |
detail |
string |
3 | - |
at |
google.protobuf.Timestamp |
4 | - |
ClusterNode
Section titled “ClusterNode”| Field | Type | Number | Description |
|---|---|---|---|
id |
string |
1 | - |
hostname |
string |
2 | - |
role |
string |
3 | panel | agent | standalone |
status |
string |
4 | healthy | degraded | unreachable | decommissioning |
version |
string |
5 | - |
ip_address |
string |
6 | - |
last_heartbeat_at |
google.protobuf.Timestamp |
7 | - |
joined_at |
google.protobuf.Timestamp |
8 | - |
certificate_expires_at |
google.protobuf.Timestamp |
9 | - |
capabilities |
repeated string |
10 | - |
account_count |
int64 |
11 | - |
site_count |
int64 |
12 | - |
mailbox_count |
int64 |
13 | - |
db_count |
int64 |
14 | - |
ClusterTopology
Section titled “ClusterTopology”| Field | Type | Number | Description |
|---|---|---|---|
panel_node_id |
string |
1 | - |
agent_node_ids |
repeated string |
2 | - |
total_capacity |
int64 |
3 | - |
current_load |
int64 |
4 | - |
CreateEnrolmentTokenRequest
Section titled “CreateEnrolmentTokenRequest”| Field | Type | Number | Description |
|---|---|---|---|
target_role |
string |
1 | - |
ttl_seconds |
int64 |
2 | - |
DecommissionNodeRequest
Section titled “DecommissionNodeRequest”| Field | Type | Number | Description |
|---|---|---|---|
id |
string |
1 | - |
drain |
bool |
2 | - |
force |
bool |
3 | - |
target_node |
string |
4 | - |
Empty is returned by RPCs whose REST route answers with an empty object or 204 No Content.
No fields.
EnrolmentToken
Section titled “EnrolmentToken”| Field | Type | Number | Description |
|---|---|---|---|
token |
string |
1 | - |
target_role |
string |
2 | - |
created_by_user_id |
string |
3 | - |
created_at |
google.protobuf.Timestamp |
4 | - |
expires_at |
google.protobuf.Timestamp |
5 | - |
used_at |
google.protobuf.Timestamp |
6 | - |
used_by_node_id |
string |
7 | - |
join_url |
string |
8 | - |
revoked |
bool |
9 | - |
GetMoveRequest
Section titled “GetMoveRequest”| Field | Type | Number | Description |
|---|---|---|---|
id |
string |
1 | - |
GetNodeRequest
Section titled “GetNodeRequest”| Field | Type | Number | Description |
|---|---|---|---|
id |
string |
1 | - |
GetTopologyRequest
Section titled “GetTopologyRequest”No fields.
ListEnrolmentTokensRequest
Section titled “ListEnrolmentTokensRequest”| Field | Type | Number | Description |
|---|---|---|---|
include_used |
bool |
1 | - |
include_expired |
bool |
2 | - |
ListEnrolmentTokensResponse
Section titled “ListEnrolmentTokensResponse”| Field | Type | Number | Description |
|---|---|---|---|
tokens |
repeated EnrolmentToken |
1 | - |
ListMovesRequest
Section titled “ListMovesRequest”| Field | Type | Number | Description |
|---|---|---|---|
account_id |
string |
1 | - |
drain_id |
string |
2 | - |
limit |
int64 |
3 | - |
ListMovesResponse
Section titled “ListMovesResponse”| Field | Type | Number | Description |
|---|---|---|---|
moves |
repeated AccountMove |
1 | - |
ListNodesRequest
Section titled “ListNodesRequest”| Field | Type | Number | Description |
|---|---|---|---|
role |
string |
1 | - |
status |
string |
2 | - |
limit |
int64 |
3 | - |
offset |
int64 |
4 | - |
ListNodesResponse
Section titled “ListNodesResponse”| Field | Type | Number | Description |
|---|---|---|---|
nodes |
repeated ClusterNode |
1 | - |
MoveAccountRequest
Section titled “MoveAccountRequest”| Field | Type | Number | Description |
|---|---|---|---|
account_id |
string |
1 | - |
target_node |
string |
2 | - |
MoveAccountResponse
Section titled “MoveAccountResponse”| Field | Type | Number | Description |
|---|---|---|---|
move |
AccountMove |
1 | - |
workflow_id |
string |
2 | - |
RevokeEnrolmentTokenRequest
Section titled “RevokeEnrolmentTokenRequest”| Field | Type | Number | Description |
|---|---|---|---|
token |
string |
1 | - |
RotateNodeCertRequest
Section titled “RotateNodeCertRequest”| Field | Type | Number | Description |
|---|---|---|---|
id |
string |
1 | - |
StreamClusterEventsRequest
Section titled “StreamClusterEventsRequest”No fields.
TriggerHealthCheckRequest
Section titled “TriggerHealthCheckRequest”| Field | Type | Number | Description |
|---|---|---|---|
id |
string |
1 | - |
WorkflowAccepted
Section titled “WorkflowAccepted”WorkflowAccepted is the body of every 202 response that only starts a workflow saga. Follow progress with WorkflowService.StreamWorkflow.
| Field | Type | Number | Description |
|---|---|---|---|
workflow_id |
string |
1 | - |