- Update CI (unit-test.yml, pr-test.yml) to use yaoapp/tai:1.2.0 with new default ports (gRPC:19100, HTTP:8099, VNC:16080, Docker:12375) - Add explicit 0.0.0.0 bind for containerized Tai instances - Fix sandbox/v2 grpc.go default port fallback (9100 → 19100) - Fix tai/tunnel/proxy.go fallback ports (8080→8099, 6080→16080) - Sync tai SDK and sandbox/v2 documentation with implementation - Add new docs: api.md, registry.md, tunnel.md Made-with: Cursor
135 lines
3.8 KiB
Markdown
135 lines
3.8 KiB
Markdown
# Package `api`
|
|
|
|
HTTP handlers for Tai node registration, heartbeat, and unregistration. Built on [Gin](https://github.com/gin-gonic/gin), these handlers are mounted on the Yao server to allow remote Tai instances to register themselves.
|
|
|
|
## Routes
|
|
|
|
| Method | Path | Handler | Description |
|
|
|--------|------|---------|-------------|
|
|
| `POST` | `/tai-nodes/register` | `HandleRegister` | Register a Tai node |
|
|
| `POST` | `/tai-nodes/heartbeat` | `HandleHeartbeat` | Update heartbeat timestamp |
|
|
| `DELETE` | `/tai-nodes/register/:tai_id` | `HandleUnregister` | Remove a Tai node |
|
|
|
|
All endpoints require a `Bearer` token in the `Authorization` header. Tokens are validated via the Yao OAuth service.
|
|
|
|
## Authentication
|
|
|
|
```
|
|
Authorization: Bearer <access_token>
|
|
```
|
|
|
|
The token is validated against `oauth.OAuth.AuthenticateToken()`. On success, an `AuthInfo` is extracted containing `Subject`, `UserID`, `ClientID`, `Scope`, `TeamID`, and `TenantID`. The `ClientID` is used for ownership checks on heartbeat and unregister.
|
|
|
|
## Endpoints
|
|
|
|
### POST /tai-nodes/register
|
|
|
|
Registers a new Tai node in the global registry.
|
|
|
|
**Request Body:**
|
|
|
|
```json
|
|
{
|
|
"tai_id": "tai-abc123",
|
|
"machine_id": "m-001",
|
|
"version": "1.2.0",
|
|
"addr": "192.168.1.100",
|
|
"ports": {"grpc": 19100, "http": 8099, "vnc": 16080, "docker": 12375},
|
|
"capabilities": {"docker": true, "host_exec": true},
|
|
"system": {
|
|
"os": "linux",
|
|
"arch": "amd64",
|
|
"hostname": "docker-host-01",
|
|
"num_cpu": 16,
|
|
"total_mem": 34359738368
|
|
}
|
|
}
|
|
```
|
|
|
|
| Field | Type | Required | Description |
|
|
|-------|------|----------|-------------|
|
|
| `tai_id` | string | yes | Unique identifier for this Tai instance |
|
|
| `machine_id` | string | no | Host machine identifier |
|
|
| `version` | string | no | Tai version string |
|
|
| `addr` | string | no | Reachable address of the Tai server |
|
|
| `ports` | map[string]int | no | Service ports (grpc, http, vnc, docker, k8s) |
|
|
| `capabilities` | map[string]bool | no | Supported features (docker, k8s, host_exec) |
|
|
| `system` | object | no | Host system information |
|
|
|
|
**Response (200):**
|
|
|
|
```json
|
|
{
|
|
"status": "registered",
|
|
"tai_id": "tai-abc123",
|
|
"remote_ip": "203.0.113.50"
|
|
}
|
|
```
|
|
|
|
**Errors:**
|
|
|
|
| Code | Condition |
|
|
|------|-----------|
|
|
| 400 | Missing `tai_id` or invalid JSON body |
|
|
| 401 | Missing or invalid Bearer token |
|
|
| 500 | Registry not initialized |
|
|
|
|
### POST /tai-nodes/heartbeat
|
|
|
|
Updates the `LastPing` timestamp for a registered node. The node's `ClientID` must match the token's `ClientID`.
|
|
|
|
**Request Body:**
|
|
|
|
```json
|
|
{
|
|
"tai_id": "tai-abc123"
|
|
}
|
|
```
|
|
|
|
**Response (200):**
|
|
|
|
```json
|
|
{
|
|
"status": "ok"
|
|
}
|
|
```
|
|
|
|
**Errors:**
|
|
|
|
| Code | Condition |
|
|
|------|-----------|
|
|
| 400 | Missing `tai_id` or invalid JSON body |
|
|
| 401 | Missing or invalid Bearer token |
|
|
| 403 | `tai_id` belongs to a different client |
|
|
| 404 | `tai_id` not found in registry |
|
|
| 500 | Registry not initialized |
|
|
|
|
### DELETE /tai-nodes/register/:tai_id
|
|
|
|
Removes a registered node. The node's `ClientID` must match the token's `ClientID`.
|
|
|
|
**Response (200):**
|
|
|
|
```json
|
|
{
|
|
"status": "unregistered"
|
|
}
|
|
```
|
|
|
|
**Errors:**
|
|
|
|
| Code | Condition |
|
|
|------|-----------|
|
|
| 400 | Missing `tai_id` path parameter |
|
|
| 401 | Missing or invalid Bearer token |
|
|
| 403 | `tai_id` belongs to a different client |
|
|
| 404 | `tai_id` not found in registry |
|
|
| 500 | Registry not initialized |
|
|
|
|
## Node Mode
|
|
|
|
Nodes registered via this HTTP API are marked with `Mode: "direct"`. This means the Yao server can reach the Tai instance directly over the network. For tunnel-mode nodes (registered via WebSocket), see [registry.md](registry.md).
|
|
|
|
## Health Check
|
|
|
|
The registry runs a background health checker (started via `Registry.StartHealthCheck`). Direct-mode nodes that miss heartbeats beyond the configured timeout are marked `"offline"`. Nodes that remain offline longer than the cleanup threshold are automatically unregistered.
|