openvibers/openvibe.contracts Commits
Add the bot service lifecycle manifest (#8)
Changes
@@@ -2,7 +2,7 @@"$schema": "https://json-schema.org/draft/2020-12/schema","$id": "https://openvibe.network/contracts/bot/robot-manage-result.v1.json","title": "BotRobotManageResult",-- "description": "bot.robot-manage-result@1: answers of bot.robot.manage on OpenVibe.Bot. POST /api/v1/robots → 201 { robot, pairing }; PATCH …/robots/:id and POST …/robots/:id/estop/clear → { robot }; DELETE …/robots/:id → 204 (no body); POST …/robots/:id/pairing-code → 201 { code, expires_at, installer }; POST …/robots/:id/operators → 201 { operators }; DELETE …/robots/:id/operators/:subject → { operators }; GET …/robots/:id/audit?limit=&before= → { audit, next_before } (newest first); POST …/devices/:id/rotate and /revoke → bot.device-connect-result@1.",++ "description": "bot.robot-manage-result@1: answers of bot.robot.manage on OpenVibe.Bot. POST /api/v1/robots → 201 { robot, pairing }; PATCH …/robots/:id and POST …/robots/:id/estop/clear → { robot }; DELETE …/robots/:id → 204 (no body); POST …/robots/:id/pairing-code → 201 { code, expires_at, installer }; POST …/robots/:id/operators → 201 { operators }; DELETE …/robots/:id/operators/:subject → { operators }; POST …/devices/:id/rotate and /revoke → bot.device-connect-result@1.","anyOf": [{"type": "object",@@@ -118,99 +118,6 @@},{"$ref": "device-connect-result.v1.json"-- },-- {-- "type": "object",-- "required": [-- "audit",-- "next_before"-- ],-- "additionalProperties": false,-- "properties": {-- "next_before": {-- "type": [-- "integer",-- "null"-- ]-- },-- "audit": {-- "type": "array",-- "items": {-- "type": "object",-- "required": [-- "id",-- "robot_id",-- "kind",-- "result",-- "at"-- ],-- "properties": {-- "id": {-- "type": "integer"-- },-- "robot_id": {-- "type": "string",-- "pattern": "^rob_[0-9A-HJKMNP-TV-Z]{26}$"-- },-- "device_id": {-- "type": [-- "string",-- "null"-- ]-- },-- "operator_subject": {-- "type": [-- "string",-- "null"-- ]-- },-- "operator_kind": {-- "type": [-- "string",-- "null"-- ]-- },-- "role": {-- "type": [-- "string",-- "null"-- ]-- },-- "kind": {-- "type": [-- "string",-- "null"-- ]-- },-- "value": {},-- "result": {-- "enum": [-- "ack",-- "nack",-- "refused",-- "expired"-- ]-- },-- "reason": {-- "type": [-- "string",-- "null"-- ]-- },-- "latency_ms": {-- "type": [-- "integer",-- "null"-- ]-- },-- "at": {-- "type": "string",-- "format": "date-time"-- }-- }-- }-- }-- }}]}@@@ -2,7 +2,7 @@"$schema": "https://json-schema.org/draft/2020-12/schema","$id": "https://openvibe.network/contracts/bot/robot-read-result.v1.json","title": "BotRobotReadResult",-- "description": "bot.robot-read-result@1: answers of bot.robot.read on OpenVibe.Bot. GET /api/v1/robots?owner= → { robots }; GET …/robots/:id → { robot, role } (role \"service\" for a service token); GET …/robots/:id/operators → { operators }; GET …/robots/:id/devices → { devices } (no hashes, with online).",++ "description": "bot.robot-read-result@1: answers of bot.robot.read on OpenVibe.Bot (a service token needs no acting subject: only GET …/robots needs ?owner=). GET /api/v1/robots?owner= → { robots }; GET …/robots/:id → { robot, role }; GET …/robots/:id/operators → { operators }; GET …/robots/:id/devices → { devices } (no hashes, with online); GET …/robots/:id/audit?limit=&before= → { audit, next_before } (newest first).","anyOf": [{"type": "object",@@@ -92,6 +92,99 @@}}}++ },++ {++ "type": "object",++ "required": [++ "audit",++ "next_before"++ ],++ "additionalProperties": false,++ "properties": {++ "next_before": {++ "type": [++ "integer",++ "null"++ ]++ },++ "audit": {++ "type": "array",++ "items": {++ "type": "object",++ "required": [++ "id",++ "robot_id",++ "kind",++ "result",++ "at"++ ],++ "properties": {++ "id": {++ "type": "integer"++ },++ "robot_id": {++ "type": "string",++ "pattern": "^rob_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "device_id": {++ "type": [++ "string",++ "null"++ ]++ },++ "operator_subject": {++ "type": [++ "string",++ "null"++ ]++ },++ "operator_kind": {++ "type": [++ "string",++ "null"++ ]++ },++ "role": {++ "type": [++ "string",++ "null"++ ]++ },++ "kind": {++ "type": [++ "string",++ "null"++ ]++ },++ "value": {},++ "result": {++ "enum": [++ "ack",++ "nack",++ "refused",++ "expired"++ ]++ },++ "reason": {++ "type": [++ "string",++ "null"++ ]++ },++ "latency_ms": {++ "type": [++ "integer",++ "null"++ ]++ },++ "at": {++ "type": "string",++ "format": "date-time"++ }++ }++ }++ }++ }}]}ddeleted file mode 100644@@@ -1,12 +0,0 @@--{-- "audit": [-- {-- "id": 1,-- "robot_id": "rob_01J8Z4M2Q0R7T9YV3K6N8P1W2X",-- "kind": "drive",-- "result": "maybe",-- "at": "2026-09-29T19:20:00.000Z"-- }-- ],-- "next_before": null--}ddeleted file mode 100644@@@ -1,21 +0,0 @@--{-- "audit": [-- {-- "id": 42,-- "robot_id": "rob_01J8Z4M2Q0R7T9YV3K6N8P1W2X",-- "device_id": "dev_01J8Z4N0A1B2C3D4E5F6G7H8J9",-- "operator_subject": "usr_01J8Z3Q4R5S6T7V8W9X0Y1Z2A3",-- "operator_kind": "user",-- "role": "operator",-- "kind": "drive",-- "value": {-- "throttle": 0.6-- },-- "result": "ack",-- "reason": null,-- "latency_ms": 42,-- "at": "2026-09-29T19:20:00.000Z"-- }-- ],-- "next_before": 42--}nnew file mode 100644@@@ -0,0 +1,12 @@++{++ "audit": [++ {++ "id": 1,++ "robot_id": "rob_01J8Z4M2Q0R7T9YV3K6N8P1W2X",++ "kind": "drive",++ "result": "maybe",++ "at": "2026-09-29T19:20:00.000Z"++ }++ ],++ "next_before": null++}nnew file mode 100644@@@ -0,0 +1,21 @@++{++ "audit": [++ {++ "id": 42,++ "robot_id": "rob_01J8Z4M2Q0R7T9YV3K6N8P1W2X",++ "device_id": "dev_01J8Z4N0A1B2C3D4E5F6G7H8J9",++ "operator_subject": "usr_01J8Z3Q4R5S6T7V8W9X0Y1Z2A3",++ "operator_kind": "user",++ "role": "operator",++ "kind": "drive",++ "value": {++ "throttle": 0.6++ },++ "result": "ack",++ "reason": null,++ "latency_ms": 42,++ "at": "2026-09-29T19:20:00.000Z"++ }++ ],++ "next_before": 42++}@@@ -62576,7 +62576,7 @@"$schema": "https://json-schema.org/draft/2020-12/schema","$id": "https://openvibe.network/contracts/bot/robot-read-result.v1.json","title": "BotRobotReadResult",-- "description": "bot.robot-read-result@1: answers of bot.robot.read on OpenVibe.Bot. GET /api/v1/robots?owner= → { robots }; GET …/robots/:id → { robot, role } (role \"service\" for a service token); GET …/robots/:id/operators → { operators }; GET …/robots/:id/devices → { devices } (no hashes, with online).",++ "description": "bot.robot-read-result@1: answers of bot.robot.read on OpenVibe.Bot (a service token needs no acting subject: only GET …/robots needs ?owner=). GET /api/v1/robots?owner= → { robots }; GET …/robots/:id → { robot, role }; GET …/robots/:id/operators → { operators }; GET …/robots/:id/devices → { devices } (no hashes, with online); GET …/robots/:id/audit?limit=&before= → { audit, next_before } (newest first).","anyOf": [{"type": "object",@@@ -62666,6 +62666,99 @@}}}++ },++ {++ "type": "object",++ "required": [++ "audit",++ "next_before"++ ],++ "additionalProperties": false,++ "properties": {++ "next_before": {++ "type": [++ "integer",++ "null"++ ]++ },++ "audit": {++ "type": "array",++ "items": {++ "type": "object",++ "required": [++ "id",++ "robot_id",++ "kind",++ "result",++ "at"++ ],++ "properties": {++ "id": {++ "type": "integer"++ },++ "robot_id": {++ "type": "string",++ "pattern": "^rob_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "device_id": {++ "type": [++ "string",++ "null"++ ]++ },++ "operator_subject": {++ "type": [++ "string",++ "null"++ ]++ },++ "operator_kind": {++ "type": [++ "string",++ "null"++ ]++ },++ "role": {++ "type": [++ "string",++ "null"++ ]++ },++ "kind": {++ "type": [++ "string",++ "null"++ ]++ },++ "value": {},++ "result": {++ "enum": [++ "ack",++ "nack",++ "refused",++ "expired"++ ]++ },++ "reason": {++ "type": [++ "string",++ "null"++ ]++ },++ "latency_ms": {++ "type": [++ "integer",++ "null"++ ]++ },++ "at": {++ "type": "string",++ "format": "date-time"++ }++ }++ }++ }++ }}]}@@@ -62762,7 +62855,7 @@"$schema": "https://json-schema.org/draft/2020-12/schema","$id": "https://openvibe.network/contracts/bot/robot-manage-result.v1.json","title": "BotRobotManageResult",-- "description": "bot.robot-manage-result@1: answers of bot.robot.manage on OpenVibe.Bot. POST /api/v1/robots → 201 { robot, pairing }; PATCH …/robots/:id and POST …/robots/:id/estop/clear → { robot }; DELETE …/robots/:id → 204 (no body); POST …/robots/:id/pairing-code → 201 { code, expires_at, installer }; POST …/robots/:id/operators → 201 { operators }; DELETE …/robots/:id/operators/:subject → { operators }; GET …/robots/:id/audit?limit=&before= → { audit, next_before } (newest first); POST …/devices/:id/rotate and /revoke → bot.device-connect-result@1.",++ "description": "bot.robot-manage-result@1: answers of bot.robot.manage on OpenVibe.Bot. POST /api/v1/robots → 201 { robot, pairing }; PATCH …/robots/:id and POST …/robots/:id/estop/clear → { robot }; DELETE …/robots/:id → 204 (no body); POST …/robots/:id/pairing-code → 201 { code, expires_at, installer }; POST …/robots/:id/operators → 201 { operators }; DELETE …/robots/:id/operators/:subject → { operators }; POST …/devices/:id/rotate and /revoke → bot.device-connect-result@1.","anyOf": [{"type": "object",@@@ -62878,99 +62971,6 @@},{"$ref": "device-connect-result.v1.json"-- },-- {-- "type": "object",-- "required": [-- "audit",-- "next_before"-- ],-- "additionalProperties": false,-- "properties": {-- "next_before": {-- "type": [-- "integer",-- "null"-- ]-- },-- "audit": {-- "type": "array",-- "items": {-- "type": "object",-- "required": [-- "id",-- "robot_id",-- "kind",-- "result",-- "at"-- ],-- "properties": {-- "id": {-- "type": "integer"-- },-- "robot_id": {-- "type": "string",-- "pattern": "^rob_[0-9A-HJKMNP-TV-Z]{26}$"-- },-- "device_id": {-- "type": [-- "string",-- "null"-- ]-- },-- "operator_subject": {-- "type": [-- "string",-- "null"-- ]-- },-- "operator_kind": {-- "type": [-- "string",-- "null"-- ]-- },-- "role": {-- "type": [-- "string",-- "null"-- ]-- },-- "kind": {-- "type": [-- "string",-- "null"-- ]-- },-- "value": {},-- "result": {-- "enum": [-- "ack",-- "nack",-- "refused",-- "expired"-- ]-- },-- "reason": {-- "type": [-- "string",-- "null"-- ]-- },-- "latency_ms": {-- "type": [-- "integer",-- "null"-- ]-- },-- "at": {-- "type": "string",-- "format": "date-time"-- }-- }-- }-- }-- }}]}@@@ -20,7 +20,7 @@"post": {"operationId": "post_api_v1_devices_id_revoke","summary": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it",-- "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, read its command audit (newest first), clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",++ "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).","tags": ["bot.robot"],@@@ -86,7 +86,7 @@"post": {"operationId": "post_api_v1_devices_id_rotate","summary": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it",-- "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, read its command audit (newest first), clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",++ "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).","tags": ["bot.robot"],@@@ -152,7 +152,7 @@"get": {"operationId": "get_api_v1_robots","summary": "Read robots with a Network service token.",-- "description": "**bot.robot.read** (first-party): Read robots with a Network service token. GET /robots needs ?owner= and lists that person's robots; the robot routes answer for any robot id with role \"service\": Bot does not check X-OV-Subject or any person's membership for a service token (a person's own token is held to owner, operator or viewer). Devices never carry a credential or key hash. The command audit is not here: Bot gates it with bot.robot.manage. Bot also requires this capability, beside bot.robot.control, to latch the e-stop.",++ "description": "**bot.robot.read** (first-party): Read robots with a Network service token. GET /robots needs ?owner= and lists that person's robots; the robot routes answer for any robot id with role \"service\": Bot does not check X-OV-Subject or any person's membership for a service token (a person's own token is held to owner, operator or viewer). Devices never carry a credential or key hash. The command audit (GET /robots/:id/audit, newest first, paged) is read too, for any robot id. Bot also requires this capability, beside bot.robot.control, to latch the e-stop.","tags": ["bot.robot"],@@@ -196,7 +196,7 @@"post": {"operationId": "post_api_v1_robots","summary": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it",-- "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, read its command audit (newest first), clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",++ "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).","tags": ["bot.robot"],@@@ -252,7 +252,7 @@"delete": {"operationId": "delete_api_v1_robots_id","summary": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it",-- "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, read its command audit (newest first), clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",++ "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).","tags": ["bot.robot"],@@@ -309,7 +309,7 @@"get": {"operationId": "get_api_v1_robots_id","summary": "Read robots with a Network service token.",-- "description": "**bot.robot.read** (first-party): Read robots with a Network service token. GET /robots needs ?owner= and lists that person's robots; the robot routes answer for any robot id with role \"service\": Bot does not check X-OV-Subject or any person's membership for a service token (a person's own token is held to owner, operator or viewer). Devices never carry a credential or key hash. The command audit is not here: Bot gates it with bot.robot.manage. Bot also requires this capability, beside bot.robot.control, to latch the e-stop.",++ "description": "**bot.robot.read** (first-party): Read robots with a Network service token. GET /robots needs ?owner= and lists that person's robots; the robot routes answer for any robot id with role \"service\": Bot does not check X-OV-Subject or any person's membership for a service token (a person's own token is held to owner, operator or viewer). Devices never carry a credential or key hash. The command audit (GET /robots/:id/audit, newest first, paged) is read too, for any robot id. Bot also requires this capability, beside bot.robot.control, to latch the e-stop.","tags": ["bot.robot"],@@@ -363,7 +363,7 @@"patch": {"operationId": "patch_api_v1_robots_id","summary": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it",-- "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, read its command audit (newest first), clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",++ "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).","tags": ["bot.robot"],@@@ -428,28 +428,25 @@"/api/v1/robots/{id}/audit": {"get": {"operationId": "get_api_v1_robots_id_audit",-- "summary": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it",-- "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, read its command audit (newest first), clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",++ "summary": "Read robots with a Network service token.",++ "description": "**bot.robot.read** (first-party): Read robots with a Network service token. GET /robots needs ?owner= and lists that person's robots; the robot routes answer for any robot id with role \"service\": Bot does not check X-OV-Subject or any person's membership for a service token (a person's own token is held to owner, operator or viewer). Devices never carry a credential or key hash. The command audit (GET /robots/:id/audit, newest first, paged) is read too, for any robot id. Bot also requires this capability, beside bot.robot.control, to latch the e-stop.","tags": ["bot.robot"],"x-openvibe-capabilities": [-- "bot.robot.manage"++ "bot.robot.read"],"x-openvibe-visibility": ["first-party"],-- "x-openvibe-quota-class": "bot-manage",++ "x-openvibe-quota-class": "bot-read","security": [{"openvibeToken": [-- "bot.robot.manage"++ "bot.robot.read"]}],-- "x-openvibe-input": {-- "$ref": "#/components/schemas/bot.robot-manage-request.v1"-- },"parameters": [{"name": "id",@@@ -466,7 +463,7 @@"content": {"application/json": {"schema": {-- "$ref": "#/components/schemas/bot.robot-manage-result.v1"++ "$ref": "#/components/schemas/bot.robot-read-result.v1"}}}@@@ -488,7 +485,7 @@"get": {"operationId": "get_api_v1_robots_id_devices","summary": "Read robots with a Network service token.",-- "description": "**bot.robot.read** (first-party): Read robots with a Network service token. GET /robots needs ?owner= and lists that person's robots; the robot routes answer for any robot id with role \"service\": Bot does not check X-OV-Subject or any person's membership for a service token (a person's own token is held to owner, operator or viewer). Devices never carry a credential or key hash. The command audit is not here: Bot gates it with bot.robot.manage. Bot also requires this capability, beside bot.robot.control, to latch the e-stop.",++ "description": "**bot.robot.read** (first-party): Read robots with a Network service token. GET /robots needs ?owner= and lists that person's robots; the robot routes answer for any robot id with role \"service\": Bot does not check X-OV-Subject or any person's membership for a service token (a person's own token is held to owner, operator or viewer). Devices never carry a credential or key hash. The command audit (GET /robots/:id/audit, newest first, paged) is read too, for any robot id. Bot also requires this capability, beside bot.robot.control, to latch the e-stop.","tags": ["bot.robot"],@@@ -600,7 +597,7 @@"post": {"operationId": "post_api_v1_robots_id_estop_clear","summary": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it",-- "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, read its command audit (newest first), clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",++ "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).","tags": ["bot.robot"],@@@ -666,7 +663,7 @@"get": {"operationId": "get_api_v1_robots_id_operators","summary": "Read robots with a Network service token.",-- "description": "**bot.robot.read** (first-party): Read robots with a Network service token. GET /robots needs ?owner= and lists that person's robots; the robot routes answer for any robot id with role \"service\": Bot does not check X-OV-Subject or any person's membership for a service token (a person's own token is held to owner, operator or viewer). Devices never carry a credential or key hash. The command audit is not here: Bot gates it with bot.robot.manage. Bot also requires this capability, beside bot.robot.control, to latch the e-stop.",++ "description": "**bot.robot.read** (first-party): Read robots with a Network service token. GET /robots needs ?owner= and lists that person's robots; the robot routes answer for any robot id with role \"service\": Bot does not check X-OV-Subject or any person's membership for a service token (a person's own token is held to owner, operator or viewer). Devices never carry a credential or key hash. The command audit (GET /robots/:id/audit, newest first, paged) is read too, for any robot id. Bot also requires this capability, beside bot.robot.control, to latch the e-stop.","tags": ["bot.robot"],@@@ -720,7 +717,7 @@"post": {"operationId": "post_api_v1_robots_id_operators","summary": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it",-- "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, read its command audit (newest first), clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",++ "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).","tags": ["bot.robot"],@@@ -786,7 +783,7 @@"delete": {"operationId": "delete_api_v1_robots_id_operators_subject","summary": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it",-- "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, read its command audit (newest first), clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",++ "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).","tags": ["bot.robot"],@@@ -853,7 +850,7 @@"post": {"operationId": "post_api_v1_robots_id_pairing_code","summary": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it",-- "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, read its command audit (newest first), clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",++ "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).","tags": ["bot.robot"],@@@ -1121,7 +1118,7 @@},"bot.robot-manage-result.v1": {"title": "BotRobotManageResult",-- "description": "bot.robot-manage-result@1: answers of bot.robot.manage on OpenVibe.Bot. POST /api/v1/robots → 201 { robot, pairing }; PATCH …/robots/:id and POST …/robots/:id/estop/clear → { robot }; DELETE …/robots/:id → 204 (no body); POST …/robots/:id/pairing-code → 201 { code, expires_at, installer }; POST …/robots/:id/operators → 201 { operators }; DELETE …/robots/:id/operators/:subject → { operators }; GET …/robots/:id/audit?limit=&before= → { audit, next_before } (newest first); POST …/devices/:id/rotate and /revoke → bot.device-connect-result@1.",++ "description": "bot.robot-manage-result@1: answers of bot.robot.manage on OpenVibe.Bot. POST /api/v1/robots → 201 { robot, pairing }; PATCH …/robots/:id and POST …/robots/:id/estop/clear → { robot }; DELETE …/robots/:id → 204 (no body); POST …/robots/:id/pairing-code → 201 { code, expires_at, installer }; POST …/robots/:id/operators → 201 { operators }; DELETE …/robots/:id/operators/:subject → { operators }; POST …/devices/:id/rotate and /revoke → bot.device-connect-result@1.","anyOf": [{"type": "object",@@@ -1237,105 +1234,12 @@},{"$ref": "#/components/schemas/bot.device-connect-result.v1"-- },-- {-- "type": "object",-- "required": [-- "audit",-- "next_before"-- ],-- "additionalProperties": false,-- "properties": {-- "next_before": {-- "type": [-- "integer",-- "null"-- ]-- },-- "audit": {-- "type": "array",-- "items": {-- "type": "object",-- "required": [-- "id",-- "robot_id",-- "kind",-- "result",-- "at"-- ],-- "properties": {-- "id": {-- "type": "integer"-- },-- "robot_id": {-- "type": "string",-- "pattern": "^rob_[0-9A-HJKMNP-TV-Z]{26}$"-- },-- "device_id": {-- "type": [-- "string",-- "null"-- ]-- },-- "operator_subject": {-- "type": [-- "string",-- "null"-- ]-- },-- "operator_kind": {-- "type": [-- "string",-- "null"-- ]-- },-- "role": {-- "type": [-- "string",-- "null"-- ]-- },-- "kind": {-- "type": [-- "string",-- "null"-- ]-- },-- "value": {},-- "result": {-- "enum": [-- "ack",-- "nack",-- "refused",-- "expired"-- ]-- },-- "reason": {-- "type": [-- "string",-- "null"-- ]-- },-- "latency_ms": {-- "type": [-- "integer",-- "null"-- ]-- },-- "at": {-- "type": "string",-- "format": "date-time"-- }-- }-- }-- }-- }}]},"bot.robot-read-result.v1": {"title": "BotRobotReadResult",-- "description": "bot.robot-read-result@1: answers of bot.robot.read on OpenVibe.Bot. GET /api/v1/robots?owner= → { robots }; GET …/robots/:id → { robot, role } (role \"service\" for a service token); GET …/robots/:id/operators → { operators }; GET …/robots/:id/devices → { devices } (no hashes, with online).",++ "description": "bot.robot-read-result@1: answers of bot.robot.read on OpenVibe.Bot (a service token needs no acting subject: only GET …/robots needs ?owner=). GET /api/v1/robots?owner= → { robots }; GET …/robots/:id → { robot, role }; GET …/robots/:id/operators → { operators }; GET …/robots/:id/devices → { devices } (no hashes, with online); GET …/robots/:id/audit?limit=&before= → { audit, next_before } (newest first).","anyOf": [{"type": "object",@@@ -1425,6 +1329,99 @@}}}++ },++ {++ "type": "object",++ "required": [++ "audit",++ "next_before"++ ],++ "additionalProperties": false,++ "properties": {++ "next_before": {++ "type": [++ "integer",++ "null"++ ]++ },++ "audit": {++ "type": "array",++ "items": {++ "type": "object",++ "required": [++ "id",++ "robot_id",++ "kind",++ "result",++ "at"++ ],++ "properties": {++ "id": {++ "type": "integer"++ },++ "robot_id": {++ "type": "string",++ "pattern": "^rob_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "device_id": {++ "type": [++ "string",++ "null"++ ]++ },++ "operator_subject": {++ "type": [++ "string",++ "null"++ ]++ },++ "operator_kind": {++ "type": [++ "string",++ "null"++ ]++ },++ "role": {++ "type": [++ "string",++ "null"++ ]++ },++ "kind": {++ "type": [++ "string",++ "null"++ ]++ },++ "value": {},++ "result": {++ "enum": [++ "ack",++ "nack",++ "refused",++ "expired"++ ]++ },++ "reason": {++ "type": [++ "string",++ "null"++ ]++ },++ "latency_ms": {++ "type": [++ "integer",++ "null"++ ]++ },++ "at": {++ "type": "string",++ "format": "date-time"++ }++ }++ }++ }++ }}]},@@@ -52231,7 +52231,7 @@ export interface BotDevice {/** [email protected] (owner: bot) *//**-- * bot.robot-read-result@1: answers of bot.robot.read on OpenVibe.Bot. GET /api/v1/robots?owner= → { robots }; GET …/robots/:id → { robot, role } (role "service" for a service token); GET …/robots/:id/operators → { operators }; GET …/robots/:id/devices → { devices } (no hashes, with online).++ * bot.robot-read-result@1: answers of bot.robot.read on OpenVibe.Bot (a service token needs no acting subject: only GET …/robots needs ?owner=). GET /api/v1/robots?owner= → { robots }; GET …/robots/:id → { robot, role }; GET …/robots/:id/operators → { operators }; GET …/robots/:id/devices → { devices } (no hashes, with online); GET …/robots/:id/audit?limit=&before= → { audit, next_before } (newest first).*/export type BotRobotReadResult =| {@@@ -52251,6 +52251,23 @@ export type BotRobotReadResult =}| {devices: BotDevice[];++ }++ | {++ next_before: number | null;++ audit: {++ id: number;++ robot_id: string;++ device_id?: string | null;++ operator_subject?: string | null;++ operator_kind?: string | null;++ role?: string | null;++ kind: string | null;++ value?: unknown;++ result: "ack" | "nack" | "refused" | "expired";++ reason?: string | null;++ latency_ms?: number | null;++ at: string;++ }[];};/** [email protected] (owner: bot) */@@@ -52277,7 +52294,7 @@ export type BotRobotManageRequest =/** [email protected] (owner: bot) *//**-- * bot.robot-manage-result@1: answers of bot.robot.manage on OpenVibe.Bot. POST /api/v1/robots → 201 { robot, pairing }; PATCH …/robots/:id and POST …/robots/:id/estop/clear → { robot }; DELETE …/robots/:id → 204 (no body); POST …/robots/:id/pairing-code → 201 { code, expires_at, installer }; POST …/robots/:id/operators → 201 { operators }; DELETE …/robots/:id/operators/:subject → { operators }; GET …/robots/:id/audit?limit=&before= → { audit, next_before } (newest first); POST …/devices/:id/rotate and /revoke → bot.device-connect-result@1.++ * bot.robot-manage-result@1: answers of bot.robot.manage on OpenVibe.Bot. POST /api/v1/robots → 201 { robot, pairing }; PATCH …/robots/:id and POST …/robots/:id/estop/clear → { robot }; DELETE …/robots/:id → 204 (no body); POST …/robots/:id/pairing-code → 201 { code, expires_at, installer }; POST …/robots/:id/operators → 201 { operators }; DELETE …/robots/:id/operators/:subject → { operators }; POST …/devices/:id/rotate and /revoke → bot.device-connect-result@1.*/export type BotRobotManageResult =| {@@@ -52307,24 +52324,7 @@ export type BotRobotManageResult =created_at?: string;}[];}-- | BotDeviceConnectResult-- | {-- next_before: number | null;-- audit: {-- id: number;-- robot_id: string;-- device_id?: string | null;-- operator_subject?: string | null;-- operator_kind?: string | null;-- role?: string | null;-- kind: string | null;-- value?: unknown;-- result: "ack" | "nack" | "refused" | "expired";-- reason?: string | null;-- latency_ms?: number | null;-- at: string;-- }[];-- };++ | BotDeviceConnectResult;/** [email protected] (owner: bot) *//*** bot.robot-control-result@1: answers of bot.robot.control on OpenVibe.Bot. POST /api/v1/robots/:id/estop → { robot } with its e-stop as it now stands.@@@ -5,7 +5,7 @@"status": "active","visibility": "first-party","sensitive": true,-- "description": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, read its command audit (newest first), clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",++ "description": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).","permissions": ["bot:robot:manage"],@@@ -23,7 +23,6 @@"POST /api/v1/robots/:id/pairing-code","POST /api/v1/robots/:id/operators","DELETE /api/v1/robots/:id/operators/:subject",-- "GET /api/v1/robots/:id/audit","POST /api/v1/robots/:id/estop/clear","POST /api/v1/devices/:id/rotate","POST /api/v1/devices/:id/revoke"@@@ -4,7 +4,7 @@"owner": "bot","status": "active","visibility": "first-party",-- "description": "Read robots with a Network service token. GET /robots needs ?owner= and lists that person's robots; the robot routes answer for any robot id with role \"service\": Bot does not check X-OV-Subject or any person's membership for a service token (a person's own token is held to owner, operator or viewer). Devices never carry a credential or key hash. The command audit is not here: Bot gates it with bot.robot.manage. Bot also requires this capability, beside bot.robot.control, to latch the e-stop.",++ "description": "Read robots with a Network service token. GET /robots needs ?owner= and lists that person's robots; the robot routes answer for any robot id with role \"service\": Bot does not check X-OV-Subject or any person's membership for a service token (a person's own token is held to owner, operator or viewer). Devices never carry a credential or key hash. The command audit (GET /robots/:id/audit, newest first, paged) is read too, for any robot id. Bot also requires this capability, beside bot.robot.control, to latch the e-stop.","permissions": ["bot:robot:read"],@@@ -17,7 +17,8 @@"GET /api/v1/robots","GET /api/v1/robots/:id","GET /api/v1/robots/:id/operators",-- "GET /api/v1/robots/:id/devices"++ "GET /api/v1/robots/:id/devices",++ "GET /api/v1/robots/:id/audit"],"inputSchema": "common.no-body@1","outputSchema": "bot.robot-read-result@1"
@@ -2,7 +2,7 @@
@@ -2,7 +2,7 @@
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://openvibe.network/contracts/bot/robot-manage-result.v1.json",
"$id": "https://openvibe.network/contracts/bot/robot-manage-result.v1.json",
"title": "BotRobotManageResult",
"title": "BotRobotManageResult",
- "description": "bot.robot-manage-result@1: answers of bot.robot.manage on OpenVibe.Bot. POST /api/v1/robots → 201 { robot, pairing }; PATCH …/robots/:id and POST …/robots/:id/estop/clear → { robot }; DELETE …/robots/:id → 204 (no body); POST …/robots/:id/pairing-code → 201 { code, expires_at, installer }; POST …/robots/:id/operators → 201 { operators }; DELETE …/robots/:id/operators/:subject → { operators }; GET …/robots/:id/audit?limit=&before= → { audit, next_before } (newest first); POST …/devices/:id/rotate and /revoke → bot.device-connect-result@1.",
+ "description": "bot.robot-manage-result@1: answers of bot.robot.manage on OpenVibe.Bot. POST /api/v1/robots → 201 { robot, pairing }; PATCH …/robots/:id and POST …/robots/:id/estop/clear → { robot }; DELETE …/robots/:id → 204 (no body); POST …/robots/:id/pairing-code → 201 { code, expires_at, installer }; POST …/robots/:id/operators → 201 { operators }; DELETE …/robots/:id/operators/:subject → { operators }; POST …/devices/:id/rotate and /revoke → bot.device-connect-result@1.",
"anyOf": [
"anyOf": [
{
{
"type": "object",
"type": "object",
@@ -118,99 +118,6 @@
@@ -118,99 +118,6 @@
},
},
{
{
"$ref": "device-connect-result.v1.json"
"$ref": "device-connect-result.v1.json"
- },
- {
- "type": "object",
- "required": [
- "audit",
- "next_before"
- ],
- "additionalProperties": false,
- "properties": {
- "next_before": {
- "type": [
- "integer",
- "null"
- ]
- },
- "audit": {
- "type": "array",
- "items": {
- "type": "object",
- "required": [
- "id",
- "robot_id",
- "kind",
- "result",
- "at"
- ],
- "properties": {
- "id": {
- "type": "integer"
- },
- "robot_id": {
- "type": "string",
- "pattern": "^rob_[0-9A-HJKMNP-TV-Z]{26}$"
- },
- "device_id": {
- "type": [
- "string",
- "null"
- ]
- },
- "operator_subject": {
- "type": [
- "string",
- "null"
- ]
- },
- "operator_kind": {
- "type": [
- "string",
- "null"
- ]
- },
- "role": {
- "type": [
- "string",
- "null"
- ]
- },
- "kind": {
- "type": [
- "string",
- "null"
- ]
- },
- "value": {},
- "result": {
- "enum": [
- "ack",
- "nack",
- "refused",
- "expired"
- ]
- },
- "reason": {
- "type": [
- "string",
- "null"
- ]
- },
- "latency_ms": {
- "type": [
- "integer",
- "null"
- ]
- },
- "at": {
- "type": "string",
- "format": "date-time"
- }
- }
- }
- }
- }
}
}
]
]
}
}
@@ -2,7 +2,7 @@
@@ -2,7 +2,7 @@
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://openvibe.network/contracts/bot/robot-read-result.v1.json",
"$id": "https://openvibe.network/contracts/bot/robot-read-result.v1.json",
"title": "BotRobotReadResult",
"title": "BotRobotReadResult",
- "description": "bot.robot-read-result@1: answers of bot.robot.read on OpenVibe.Bot. GET /api/v1/robots?owner= → { robots }; GET …/robots/:id → { robot, role } (role \"service\" for a service token); GET …/robots/:id/operators → { operators }; GET …/robots/:id/devices → { devices } (no hashes, with online).",
+ "description": "bot.robot-read-result@1: answers of bot.robot.read on OpenVibe.Bot (a service token needs no acting subject: only GET …/robots needs ?owner=). GET /api/v1/robots?owner= → { robots }; GET …/robots/:id → { robot, role }; GET …/robots/:id/operators → { operators }; GET …/robots/:id/devices → { devices } (no hashes, with online); GET …/robots/:id/audit?limit=&before= → { audit, next_before } (newest first).",
"anyOf": [
"anyOf": [
{
{
"type": "object",
"type": "object",
@@ -92,6 +92,99 @@
@@ -92,6 +92,99 @@
}
}
}
}
}
}
+ },
+ {
+ "type": "object",
+ "required": [
+ "audit",
+ "next_before"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "next_before": {
+ "type": [
+ "integer",
+ "null"
+ ]
+ },
+ "audit": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "required": [
+ "id",
+ "robot_id",
+ "kind",
+ "result",
+ "at"
+ ],
+ "properties": {
+ "id": {
+ "type": "integer"
+ },
+ "robot_id": {
+ "type": "string",
+ "pattern": "^rob_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "device_id": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "operator_subject": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "operator_kind": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "role": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "kind": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "value": {},
+ "result": {
+ "enum": [
+ "ack",
+ "nack",
+ "refused",
+ "expired"
+ ]
+ },
+ "reason": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "latency_ms": {
+ "type": [
+ "integer",
+ "null"
+ ]
+ },
+ "at": {
+ "type": "string",
+ "format": "date-time"
+ }
+ }
+ }
+ }
+ }
}
}
]
]
}
}
deleted file mode 100644
deleted file mode 100644
@@ -1,12 +0,0 @@
@@ -1,12 +0,0 @@
-{
- "audit": [
- {
- "id": 1,
- "robot_id": "rob_01J8Z4M2Q0R7T9YV3K6N8P1W2X",
- "kind": "drive",
- "result": "maybe",
- "at": "2026-09-29T19:20:00.000Z"
- }
- ],
- "next_before": null
-}
deleted file mode 100644
deleted file mode 100644
@@ -1,21 +0,0 @@
@@ -1,21 +0,0 @@
-{
- "audit": [
- {
- "id": 42,
- "robot_id": "rob_01J8Z4M2Q0R7T9YV3K6N8P1W2X",
- "device_id": "dev_01J8Z4N0A1B2C3D4E5F6G7H8J9",
- "operator_subject": "usr_01J8Z3Q4R5S6T7V8W9X0Y1Z2A3",
- "operator_kind": "user",
- "role": "operator",
- "kind": "drive",
- "value": {
- "throttle": 0.6
- },
- "result": "ack",
- "reason": null,
- "latency_ms": 42,
- "at": "2026-09-29T19:20:00.000Z"
- }
- ],
- "next_before": 42
-}
new file mode 100644
new file mode 100644
@@ -0,0 +1,12 @@
@@ -0,0 +1,12 @@
+{
+ "audit": [
+ {
+ "id": 1,
+ "robot_id": "rob_01J8Z4M2Q0R7T9YV3K6N8P1W2X",
+ "kind": "drive",
+ "result": "maybe",
+ "at": "2026-09-29T19:20:00.000Z"
+ }
+ ],
+ "next_before": null
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
+{
+ "audit": [
+ {
+ "id": 42,
+ "robot_id": "rob_01J8Z4M2Q0R7T9YV3K6N8P1W2X",
+ "device_id": "dev_01J8Z4N0A1B2C3D4E5F6G7H8J9",
+ "operator_subject": "usr_01J8Z3Q4R5S6T7V8W9X0Y1Z2A3",
+ "operator_kind": "user",
+ "role": "operator",
+ "kind": "drive",
+ "value": {
+ "throttle": 0.6
+ },
+ "result": "ack",
+ "reason": null,
+ "latency_ms": 42,
+ "at": "2026-09-29T19:20:00.000Z"
+ }
+ ],
+ "next_before": 42
+}
@@ -62576,7 +62576,7 @@
@@ -62576,7 +62576,7 @@
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://openvibe.network/contracts/bot/robot-read-result.v1.json",
"$id": "https://openvibe.network/contracts/bot/robot-read-result.v1.json",
"title": "BotRobotReadResult",
"title": "BotRobotReadResult",
- "description": "bot.robot-read-result@1: answers of bot.robot.read on OpenVibe.Bot. GET /api/v1/robots?owner= → { robots }; GET …/robots/:id → { robot, role } (role \"service\" for a service token); GET …/robots/:id/operators → { operators }; GET …/robots/:id/devices → { devices } (no hashes, with online).",
+ "description": "bot.robot-read-result@1: answers of bot.robot.read on OpenVibe.Bot (a service token needs no acting subject: only GET …/robots needs ?owner=). GET /api/v1/robots?owner= → { robots }; GET …/robots/:id → { robot, role }; GET …/robots/:id/operators → { operators }; GET …/robots/:id/devices → { devices } (no hashes, with online); GET …/robots/:id/audit?limit=&before= → { audit, next_before } (newest first).",
"anyOf": [
"anyOf": [
{
{
"type": "object",
"type": "object",
@@ -62666,6 +62666,99 @@
@@ -62666,6 +62666,99 @@
}
}
}
}
}
}
+ },
+ {
+ "type": "object",
+ "required": [
+ "audit",
+ "next_before"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "next_before": {
+ "type": [
+ "integer",
+ "null"
+ ]
+ },
+ "audit": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "required": [
+ "id",
+ "robot_id",
+ "kind",
+ "result",
+ "at"
+ ],
+ "properties": {
+ "id": {
+ "type": "integer"
+ },
+ "robot_id": {
+ "type": "string",
+ "pattern": "^rob_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "device_id": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "operator_subject": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "operator_kind": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "role": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "kind": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "value": {},
+ "result": {
+ "enum": [
+ "ack",
+ "nack",
+ "refused",
+ "expired"
+ ]
+ },
+ "reason": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "latency_ms": {
+ "type": [
+ "integer",
+ "null"
+ ]
+ },
+ "at": {
+ "type": "string",
+ "format": "date-time"
+ }
+ }
+ }
+ }
+ }
}
}
]
]
}
}
@@ -62762,7 +62855,7 @@
@@ -62762,7 +62855,7 @@
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://openvibe.network/contracts/bot/robot-manage-result.v1.json",
"$id": "https://openvibe.network/contracts/bot/robot-manage-result.v1.json",
"title": "BotRobotManageResult",
"title": "BotRobotManageResult",
- "description": "bot.robot-manage-result@1: answers of bot.robot.manage on OpenVibe.Bot. POST /api/v1/robots → 201 { robot, pairing }; PATCH …/robots/:id and POST …/robots/:id/estop/clear → { robot }; DELETE …/robots/:id → 204 (no body); POST …/robots/:id/pairing-code → 201 { code, expires_at, installer }; POST …/robots/:id/operators → 201 { operators }; DELETE …/robots/:id/operators/:subject → { operators }; GET …/robots/:id/audit?limit=&before= → { audit, next_before } (newest first); POST …/devices/:id/rotate and /revoke → bot.device-connect-result@1.",
+ "description": "bot.robot-manage-result@1: answers of bot.robot.manage on OpenVibe.Bot. POST /api/v1/robots → 201 { robot, pairing }; PATCH …/robots/:id and POST …/robots/:id/estop/clear → { robot }; DELETE …/robots/:id → 204 (no body); POST …/robots/:id/pairing-code → 201 { code, expires_at, installer }; POST …/robots/:id/operators → 201 { operators }; DELETE …/robots/:id/operators/:subject → { operators }; POST …/devices/:id/rotate and /revoke → bot.device-connect-result@1.",
"anyOf": [
"anyOf": [
{
{
"type": "object",
"type": "object",
@@ -62878,99 +62971,6 @@
@@ -62878,99 +62971,6 @@
},
},
{
{
"$ref": "device-connect-result.v1.json"
"$ref": "device-connect-result.v1.json"
- },
- {
- "type": "object",
- "required": [
- "audit",
- "next_before"
- ],
- "additionalProperties": false,
- "properties": {
- "next_before": {
- "type": [
- "integer",
- "null"
- ]
- },
- "audit": {
- "type": "array",
- "items": {
- "type": "object",
- "required": [
- "id",
- "robot_id",
- "kind",
- "result",
- "at"
- ],
- "properties": {
- "id": {
- "type": "integer"
- },
- "robot_id": {
- "type": "string",
- "pattern": "^rob_[0-9A-HJKMNP-TV-Z]{26}$"
- },
- "device_id": {
- "type": [
- "string",
- "null"
- ]
- },
- "operator_subject": {
- "type": [
- "string",
- "null"
- ]
- },
- "operator_kind": {
- "type": [
- "string",
- "null"
- ]
- },
- "role": {
- "type": [
- "string",
- "null"
- ]
- },
- "kind": {
- "type": [
- "string",
- "null"
- ]
- },
- "value": {},
- "result": {
- "enum": [
- "ack",
- "nack",
- "refused",
- "expired"
- ]
- },
- "reason": {
- "type": [
- "string",
- "null"
- ]
- },
- "latency_ms": {
- "type": [
- "integer",
- "null"
- ]
- },
- "at": {
- "type": "string",
- "format": "date-time"
- }
- }
- }
- }
- }
}
}
]
]
}
}
@@ -20,7 +20,7 @@
@@ -20,7 +20,7 @@
"post": {
"post": {
"operationId": "post_api_v1_devices_id_revoke",
"operationId": "post_api_v1_devices_id_revoke",
"summary": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it",
"summary": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it",
- "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, read its command audit (newest first), clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",
+ "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",
"tags": [
"tags": [
"bot.robot"
"bot.robot"
],
],
@@ -86,7 +86,7 @@
@@ -86,7 +86,7 @@
"post": {
"post": {
"operationId": "post_api_v1_devices_id_rotate",
"operationId": "post_api_v1_devices_id_rotate",
"summary": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it",
"summary": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it",
- "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, read its command audit (newest first), clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",
+ "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",
"tags": [
"tags": [
"bot.robot"
"bot.robot"
],
],
@@ -152,7 +152,7 @@
@@ -152,7 +152,7 @@
"get": {
"get": {
"operationId": "get_api_v1_robots",
"operationId": "get_api_v1_robots",
"summary": "Read robots with a Network service token.",
"summary": "Read robots with a Network service token.",
- "description": "**bot.robot.read** (first-party): Read robots with a Network service token. GET /robots needs ?owner= and lists that person's robots; the robot routes answer for any robot id with role \"service\": Bot does not check X-OV-Subject or any person's membership for a service token (a person's own token is held to owner, operator or viewer). Devices never carry a credential or key hash. The command audit is not here: Bot gates it with bot.robot.manage. Bot also requires this capability, beside bot.robot.control, to latch the e-stop.",
+ "description": "**bot.robot.read** (first-party): Read robots with a Network service token. GET /robots needs ?owner= and lists that person's robots; the robot routes answer for any robot id with role \"service\": Bot does not check X-OV-Subject or any person's membership for a service token (a person's own token is held to owner, operator or viewer). Devices never carry a credential or key hash. The command audit (GET /robots/:id/audit, newest first, paged) is read too, for any robot id. Bot also requires this capability, beside bot.robot.control, to latch the e-stop.",
"tags": [
"tags": [
"bot.robot"
"bot.robot"
],
],
@@ -196,7 +196,7 @@
@@ -196,7 +196,7 @@
"post": {
"post": {
"operationId": "post_api_v1_robots",
"operationId": "post_api_v1_robots",
"summary": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it",
"summary": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it",
- "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, read its command audit (newest first), clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",
+ "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",
"tags": [
"tags": [
"bot.robot"
"bot.robot"
],
],
@@ -252,7 +252,7 @@
@@ -252,7 +252,7 @@
"delete": {
"delete": {
"operationId": "delete_api_v1_robots_id",
"operationId": "delete_api_v1_robots_id",
"summary": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it",
"summary": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it",
- "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, read its command audit (newest first), clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",
+ "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",
"tags": [
"tags": [
"bot.robot"
"bot.robot"
],
],
@@ -309,7 +309,7 @@
@@ -309,7 +309,7 @@
"get": {
"get": {
"operationId": "get_api_v1_robots_id",
"operationId": "get_api_v1_robots_id",
"summary": "Read robots with a Network service token.",
"summary": "Read robots with a Network service token.",
- "description": "**bot.robot.read** (first-party): Read robots with a Network service token. GET /robots needs ?owner= and lists that person's robots; the robot routes answer for any robot id with role \"service\": Bot does not check X-OV-Subject or any person's membership for a service token (a person's own token is held to owner, operator or viewer). Devices never carry a credential or key hash. The command audit is not here: Bot gates it with bot.robot.manage. Bot also requires this capability, beside bot.robot.control, to latch the e-stop.",
+ "description": "**bot.robot.read** (first-party): Read robots with a Network service token. GET /robots needs ?owner= and lists that person's robots; the robot routes answer for any robot id with role \"service\": Bot does not check X-OV-Subject or any person's membership for a service token (a person's own token is held to owner, operator or viewer). Devices never carry a credential or key hash. The command audit (GET /robots/:id/audit, newest first, paged) is read too, for any robot id. Bot also requires this capability, beside bot.robot.control, to latch the e-stop.",
"tags": [
"tags": [
"bot.robot"
"bot.robot"
],
],
@@ -363,7 +363,7 @@
@@ -363,7 +363,7 @@
"patch": {
"patch": {
"operationId": "patch_api_v1_robots_id",
"operationId": "patch_api_v1_robots_id",
"summary": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it",
"summary": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it",
- "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, read its command audit (newest first), clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",
+ "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",
"tags": [
"tags": [
"bot.robot"
"bot.robot"
],
],
@@ -428,28 +428,25 @@
@@ -428,28 +428,25 @@
"/api/v1/robots/{id}/audit": {
"/api/v1/robots/{id}/audit": {
"get": {
"get": {
"operationId": "get_api_v1_robots_id_audit",
"operationId": "get_api_v1_robots_id_audit",
- "summary": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it",
- "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, read its command audit (newest first), clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",
+ "summary": "Read robots with a Network service token.",
+ "description": "**bot.robot.read** (first-party): Read robots with a Network service token. GET /robots needs ?owner= and lists that person's robots; the robot routes answer for any robot id with role \"service\": Bot does not check X-OV-Subject or any person's membership for a service token (a person's own token is held to owner, operator or viewer). Devices never carry a credential or key hash. The command audit (GET /robots/:id/audit, newest first, paged) is read too, for any robot id. Bot also requires this capability, beside bot.robot.control, to latch the e-stop.",
"tags": [
"tags": [
"bot.robot"
"bot.robot"
],
],
"x-openvibe-capabilities": [
"x-openvibe-capabilities": [
- "bot.robot.manage"
+ "bot.robot.read"
],
],
"x-openvibe-visibility": [
"x-openvibe-visibility": [
"first-party"
"first-party"
],
],
- "x-openvibe-quota-class": "bot-manage",
+ "x-openvibe-quota-class": "bot-read",
"security": [
"security": [
{
{
"openvibeToken": [
"openvibeToken": [
- "bot.robot.manage"
+ "bot.robot.read"
]
]
}
}
],
],
- "x-openvibe-input": {
- "$ref": "#/components/schemas/bot.robot-manage-request.v1"
- },
"parameters": [
"parameters": [
{
{
"name": "id",
"name": "id",
@@ -466,7 +463,7 @@
@@ -466,7 +463,7 @@
"content": {
"content": {
"application/json": {
"application/json": {
"schema": {
"schema": {
- "$ref": "#/components/schemas/bot.robot-manage-result.v1"
+ "$ref": "#/components/schemas/bot.robot-read-result.v1"
}
}
}
}
}
}
@@ -488,7 +485,7 @@
@@ -488,7 +485,7 @@
"get": {
"get": {
"operationId": "get_api_v1_robots_id_devices",
"operationId": "get_api_v1_robots_id_devices",
"summary": "Read robots with a Network service token.",
"summary": "Read robots with a Network service token.",
- "description": "**bot.robot.read** (first-party): Read robots with a Network service token. GET /robots needs ?owner= and lists that person's robots; the robot routes answer for any robot id with role \"service\": Bot does not check X-OV-Subject or any person's membership for a service token (a person's own token is held to owner, operator or viewer). Devices never carry a credential or key hash. The command audit is not here: Bot gates it with bot.robot.manage. Bot also requires this capability, beside bot.robot.control, to latch the e-stop.",
+ "description": "**bot.robot.read** (first-party): Read robots with a Network service token. GET /robots needs ?owner= and lists that person's robots; the robot routes answer for any robot id with role \"service\": Bot does not check X-OV-Subject or any person's membership for a service token (a person's own token is held to owner, operator or viewer). Devices never carry a credential or key hash. The command audit (GET /robots/:id/audit, newest first, paged) is read too, for any robot id. Bot also requires this capability, beside bot.robot.control, to latch the e-stop.",
"tags": [
"tags": [
"bot.robot"
"bot.robot"
],
],
@@ -600,7 +597,7 @@
@@ -600,7 +597,7 @@
"post": {
"post": {
"operationId": "post_api_v1_robots_id_estop_clear",
"operationId": "post_api_v1_robots_id_estop_clear",
"summary": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it",
"summary": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it",
- "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, read its command audit (newest first), clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",
+ "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",
"tags": [
"tags": [
"bot.robot"
"bot.robot"
],
],
@@ -666,7 +663,7 @@
@@ -666,7 +663,7 @@
"get": {
"get": {
"operationId": "get_api_v1_robots_id_operators",
"operationId": "get_api_v1_robots_id_operators",
"summary": "Read robots with a Network service token.",
"summary": "Read robots with a Network service token.",
- "description": "**bot.robot.read** (first-party): Read robots with a Network service token. GET /robots needs ?owner= and lists that person's robots; the robot routes answer for any robot id with role \"service\": Bot does not check X-OV-Subject or any person's membership for a service token (a person's own token is held to owner, operator or viewer). Devices never carry a credential or key hash. The command audit is not here: Bot gates it with bot.robot.manage. Bot also requires this capability, beside bot.robot.control, to latch the e-stop.",
+ "description": "**bot.robot.read** (first-party): Read robots with a Network service token. GET /robots needs ?owner= and lists that person's robots; the robot routes answer for any robot id with role \"service\": Bot does not check X-OV-Subject or any person's membership for a service token (a person's own token is held to owner, operator or viewer). Devices never carry a credential or key hash. The command audit (GET /robots/:id/audit, newest first, paged) is read too, for any robot id. Bot also requires this capability, beside bot.robot.control, to latch the e-stop.",
"tags": [
"tags": [
"bot.robot"
"bot.robot"
],
],
@@ -720,7 +717,7 @@
@@ -720,7 +717,7 @@
"post": {
"post": {
"operationId": "post_api_v1_robots_id_operators",
"operationId": "post_api_v1_robots_id_operators",
"summary": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it",
"summary": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it",
- "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, read its command audit (newest first), clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",
+ "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",
"tags": [
"tags": [
"bot.robot"
"bot.robot"
],
],
@@ -786,7 +783,7 @@
@@ -786,7 +783,7 @@
"delete": {
"delete": {
"operationId": "delete_api_v1_robots_id_operators_subject",
"operationId": "delete_api_v1_robots_id_operators_subject",
"summary": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it",
"summary": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it",
- "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, read its command audit (newest first), clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",
+ "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",
"tags": [
"tags": [
"bot.robot"
"bot.robot"
],
],
@@ -853,7 +850,7 @@
@@ -853,7 +850,7 @@
"post": {
"post": {
"operationId": "post_api_v1_robots_id_pairing_code",
"operationId": "post_api_v1_robots_id_pairing_code",
"summary": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it",
"summary": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it",
- "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, read its command audit (newest first), clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",
+ "description": "**bot.robot.manage** (first-party): Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",
"tags": [
"tags": [
"bot.robot"
"bot.robot"
],
],
@@ -1121,7 +1118,7 @@
@@ -1121,7 +1118,7 @@
},
},
"bot.robot-manage-result.v1": {
"bot.robot-manage-result.v1": {
"title": "BotRobotManageResult",
"title": "BotRobotManageResult",
- "description": "bot.robot-manage-result@1: answers of bot.robot.manage on OpenVibe.Bot. POST /api/v1/robots → 201 { robot, pairing }; PATCH …/robots/:id and POST …/robots/:id/estop/clear → { robot }; DELETE …/robots/:id → 204 (no body); POST …/robots/:id/pairing-code → 201 { code, expires_at, installer }; POST …/robots/:id/operators → 201 { operators }; DELETE …/robots/:id/operators/:subject → { operators }; GET …/robots/:id/audit?limit=&before= → { audit, next_before } (newest first); POST …/devices/:id/rotate and /revoke → bot.device-connect-result@1.",
+ "description": "bot.robot-manage-result@1: answers of bot.robot.manage on OpenVibe.Bot. POST /api/v1/robots → 201 { robot, pairing }; PATCH …/robots/:id and POST …/robots/:id/estop/clear → { robot }; DELETE …/robots/:id → 204 (no body); POST …/robots/:id/pairing-code → 201 { code, expires_at, installer }; POST …/robots/:id/operators → 201 { operators }; DELETE …/robots/:id/operators/:subject → { operators }; POST …/devices/:id/rotate and /revoke → bot.device-connect-result@1.",
"anyOf": [
"anyOf": [
{
{
"type": "object",
"type": "object",
@@ -1237,105 +1234,12 @@
@@ -1237,105 +1234,12 @@
},
},
{
{
"$ref": "#/components/schemas/bot.device-connect-result.v1"
"$ref": "#/components/schemas/bot.device-connect-result.v1"
- },
- {
- "type": "object",
- "required": [
- "audit",
- "next_before"
- ],
- "additionalProperties": false,
- "properties": {
- "next_before": {
- "type": [
- "integer",
- "null"
- ]
- },
- "audit": {
- "type": "array",
- "items": {
- "type": "object",
- "required": [
- "id",
- "robot_id",
- "kind",
- "result",
- "at"
- ],
- "properties": {
- "id": {
- "type": "integer"
- },
- "robot_id": {
- "type": "string",
- "pattern": "^rob_[0-9A-HJKMNP-TV-Z]{26}$"
- },
- "device_id": {
- "type": [
- "string",
- "null"
- ]
- },
- "operator_subject": {
- "type": [
- "string",
- "null"
- ]
- },
- "operator_kind": {
- "type": [
- "string",
- "null"
- ]
- },
- "role": {
- "type": [
- "string",
- "null"
- ]
- },
- "kind": {
- "type": [
- "string",
- "null"
- ]
- },
- "value": {},
- "result": {
- "enum": [
- "ack",
- "nack",
- "refused",
- "expired"
- ]
- },
- "reason": {
- "type": [
- "string",
- "null"
- ]
- },
- "latency_ms": {
- "type": [
- "integer",
- "null"
- ]
- },
- "at": {
- "type": "string",
- "format": "date-time"
- }
- }
- }
- }
- }
}
}
]
]
},
},
"bot.robot-read-result.v1": {
"bot.robot-read-result.v1": {
"title": "BotRobotReadResult",
"title": "BotRobotReadResult",
- "description": "bot.robot-read-result@1: answers of bot.robot.read on OpenVibe.Bot. GET /api/v1/robots?owner= → { robots }; GET …/robots/:id → { robot, role } (role \"service\" for a service token); GET …/robots/:id/operators → { operators }; GET …/robots/:id/devices → { devices } (no hashes, with online).",
+ "description": "bot.robot-read-result@1: answers of bot.robot.read on OpenVibe.Bot (a service token needs no acting subject: only GET …/robots needs ?owner=). GET /api/v1/robots?owner= → { robots }; GET …/robots/:id → { robot, role }; GET …/robots/:id/operators → { operators }; GET …/robots/:id/devices → { devices } (no hashes, with online); GET …/robots/:id/audit?limit=&before= → { audit, next_before } (newest first).",
"anyOf": [
"anyOf": [
{
{
"type": "object",
"type": "object",
@@ -1425,6 +1329,99 @@
@@ -1425,6 +1329,99 @@
}
}
}
}
}
}
+ },
+ {
+ "type": "object",
+ "required": [
+ "audit",
+ "next_before"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "next_before": {
+ "type": [
+ "integer",
+ "null"
+ ]
+ },
+ "audit": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "required": [
+ "id",
+ "robot_id",
+ "kind",
+ "result",
+ "at"
+ ],
+ "properties": {
+ "id": {
+ "type": "integer"
+ },
+ "robot_id": {
+ "type": "string",
+ "pattern": "^rob_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "device_id": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "operator_subject": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "operator_kind": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "role": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "kind": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "value": {},
+ "result": {
+ "enum": [
+ "ack",
+ "nack",
+ "refused",
+ "expired"
+ ]
+ },
+ "reason": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "latency_ms": {
+ "type": [
+ "integer",
+ "null"
+ ]
+ },
+ "at": {
+ "type": "string",
+ "format": "date-time"
+ }
+ }
+ }
+ }
+ }
}
}
]
]
},
},
@@ -52231,7 +52231,7 @@ export interface BotDevice {
@@ -52231,7 +52231,7 @@ export interface BotDevice {
/** [email protected] (owner: bot) */
/** [email protected] (owner: bot) */
/**
/**
- * bot.robot-read-result@1: answers of bot.robot.read on OpenVibe.Bot. GET /api/v1/robots?owner= → { robots }; GET …/robots/:id → { robot, role } (role "service" for a service token); GET …/robots/:id/operators → { operators }; GET …/robots/:id/devices → { devices } (no hashes, with online).
+ * bot.robot-read-result@1: answers of bot.robot.read on OpenVibe.Bot (a service token needs no acting subject: only GET …/robots needs ?owner=). GET /api/v1/robots?owner= → { robots }; GET …/robots/:id → { robot, role }; GET …/robots/:id/operators → { operators }; GET …/robots/:id/devices → { devices } (no hashes, with online); GET …/robots/:id/audit?limit=&before= → { audit, next_before } (newest first).
*/
*/
export type BotRobotReadResult =
export type BotRobotReadResult =
| {
| {
@@ -52251,6 +52251,23 @@ export type BotRobotReadResult =
@@ -52251,6 +52251,23 @@ export type BotRobotReadResult =
}
}
| {
| {
devices: BotDevice[];
devices: BotDevice[];
+ }
+ | {
+ next_before: number | null;
+ audit: {
+ id: number;
+ robot_id: string;
+ device_id?: string | null;
+ operator_subject?: string | null;
+ operator_kind?: string | null;
+ role?: string | null;
+ kind: string | null;
+ value?: unknown;
+ result: "ack" | "nack" | "refused" | "expired";
+ reason?: string | null;
+ latency_ms?: number | null;
+ at: string;
+ }[];
};
};
/** [email protected] (owner: bot) */
/** [email protected] (owner: bot) */
@@ -52277,7 +52294,7 @@ export type BotRobotManageRequest =
@@ -52277,7 +52294,7 @@ export type BotRobotManageRequest =
/** [email protected] (owner: bot) */
/** [email protected] (owner: bot) */
/**
/**
- * bot.robot-manage-result@1: answers of bot.robot.manage on OpenVibe.Bot. POST /api/v1/robots → 201 { robot, pairing }; PATCH …/robots/:id and POST …/robots/:id/estop/clear → { robot }; DELETE …/robots/:id → 204 (no body); POST …/robots/:id/pairing-code → 201 { code, expires_at, installer }; POST …/robots/:id/operators → 201 { operators }; DELETE …/robots/:id/operators/:subject → { operators }; GET …/robots/:id/audit?limit=&before= → { audit, next_before } (newest first); POST …/devices/:id/rotate and /revoke → bot.device-connect-result@1.
+ * bot.robot-manage-result@1: answers of bot.robot.manage on OpenVibe.Bot. POST /api/v1/robots → 201 { robot, pairing }; PATCH …/robots/:id and POST …/robots/:id/estop/clear → { robot }; DELETE …/robots/:id → 204 (no body); POST …/robots/:id/pairing-code → 201 { code, expires_at, installer }; POST …/robots/:id/operators → 201 { operators }; DELETE …/robots/:id/operators/:subject → { operators }; POST …/devices/:id/rotate and /revoke → bot.device-connect-result@1.
*/
*/
export type BotRobotManageResult =
export type BotRobotManageResult =
| {
| {
@@ -52307,24 +52324,7 @@ export type BotRobotManageResult =
@@ -52307,24 +52324,7 @@ export type BotRobotManageResult =
created_at?: string;
created_at?: string;
}[];
}[];
}
}
- | BotDeviceConnectResult
- | {
- next_before: number | null;
- audit: {
- id: number;
- robot_id: string;
- device_id?: string | null;
- operator_subject?: string | null;
- operator_kind?: string | null;
- role?: string | null;
- kind: string | null;
- value?: unknown;
- result: "ack" | "nack" | "refused" | "expired";
- reason?: string | null;
- latency_ms?: number | null;
- at: string;
- }[];
- };
+ | BotDeviceConnectResult;
/** [email protected] (owner: bot) */
/** [email protected] (owner: bot) */
/**
/**
* bot.robot-control-result@1: answers of bot.robot.control on OpenVibe.Bot. POST /api/v1/robots/:id/estop → { robot } with its e-stop as it now stands.
* bot.robot-control-result@1: answers of bot.robot.control on OpenVibe.Bot. POST /api/v1/robots/:id/estop → { robot } with its e-stop as it now stands.
@@ -5,7 +5,7 @@
@@ -5,7 +5,7 @@
"status": "active",
"status": "active",
"visibility": "first-party",
"visibility": "first-party",
"sensitive": true,
"sensitive": true,
- "description": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, read its command audit (newest first), clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",
+ "description": "Manage robots with a Network service token: create one for the person the body's owner or X-OV-Subject names (a new robot and its pairing code), and, for any robot id, rename, reconfigure or delete it (irreversible), issue a one-time pairing code, add or remove operators, clear its e-stop, and rotate a paired device's credentials (the new credential and publish key are shown once) or revoke the device, which closes its socket at once. Bot does not check the acting person against the robot's owner for a service token (a person's own token must be the owner's).",
"permissions": [
"permissions": [
"bot:robot:manage"
"bot:robot:manage"
],
],
@@ -23,7 +23,6 @@
@@ -23,7 +23,6 @@
"POST /api/v1/robots/:id/pairing-code",
"POST /api/v1/robots/:id/pairing-code",
"POST /api/v1/robots/:id/operators",
"POST /api/v1/robots/:id/operators",
"DELETE /api/v1/robots/:id/operators/:subject",
"DELETE /api/v1/robots/:id/operators/:subject",
- "GET /api/v1/robots/:id/audit",
"POST /api/v1/robots/:id/estop/clear",
"POST /api/v1/robots/:id/estop/clear",
"POST /api/v1/devices/:id/rotate",
"POST /api/v1/devices/:id/rotate",
"POST /api/v1/devices/:id/revoke"
"POST /api/v1/devices/:id/revoke"
@@ -4,7 +4,7 @@
@@ -4,7 +4,7 @@
"owner": "bot",
"owner": "bot",
"status": "active",
"status": "active",
"visibility": "first-party",
"visibility": "first-party",
- "description": "Read robots with a Network service token. GET /robots needs ?owner= and lists that person's robots; the robot routes answer for any robot id with role \"service\": Bot does not check X-OV-Subject or any person's membership for a service token (a person's own token is held to owner, operator or viewer). Devices never carry a credential or key hash. The command audit is not here: Bot gates it with bot.robot.manage. Bot also requires this capability, beside bot.robot.control, to latch the e-stop.",
+ "description": "Read robots with a Network service token. GET /robots needs ?owner= and lists that person's robots; the robot routes answer for any robot id with role \"service\": Bot does not check X-OV-Subject or any person's membership for a service token (a person's own token is held to owner, operator or viewer). Devices never carry a credential or key hash. The command audit (GET /robots/:id/audit, newest first, paged) is read too, for any robot id. Bot also requires this capability, beside bot.robot.control, to latch the e-stop.",
"permissions": [
"permissions": [
"bot:robot:read"
"bot:robot:read"
],
],
@@ -17,7 +17,8 @@
@@ -17,7 +17,8 @@
"GET /api/v1/robots",
"GET /api/v1/robots",
"GET /api/v1/robots/:id",
"GET /api/v1/robots/:id",
"GET /api/v1/robots/:id/operators",
"GET /api/v1/robots/:id/operators",
- "GET /api/v1/robots/:id/devices"
+ "GET /api/v1/robots/:id/devices",
+ "GET /api/v1/robots/:id/audit"
],
],
"inputSchema": "common.no-body@1",
"inputSchema": "common.no-body@1",
"outputSchema": "bot.robot-read-result@1"
"outputSchema": "bot.robot-read-result@1"