From d355955fb6ec18776cc01ffced57f306fc7bae8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iwo=20Strzebo=C5=84ski?= Date: Thu, 29 Oct 2026 15:03:27 +0000 Subject: [PATCH] Add provision_printer and remove_printer to the gateway protocol Adding a printer from the console has to put its LAN credential on the gateway without the cloud keeping it. The new server messages carry it once (documented as never-log) and are answered through the existing command_result with the request id. The message cannot name a certificate path or serial port: those are on the gateway's own disk and USB bus. --- packages/ts-types/src/schemas/edge.ts | 40 +++++++++ .../v1/edge/server_message.schema.json | 84 +++++++++++++++++++ 2 files changed, 124 insertions(+) diff --git a/packages/ts-types/src/schemas/edge.ts b/packages/ts-types/src/schemas/edge.ts index 6e6bd10..a7456c3 100644 --- a/packages/ts-types/src/schemas/edge.ts +++ b/packages/ts-types/src/schemas/edge.ts @@ -374,5 +374,45 @@ export const EdgeServerMessageSchema = Type.Union([ printer_id: Type.String(), command: PrinterCommandSchema, }), + /** + * Add a printer to this gateway. Relayed by the cloud, which keeps nothing: + * it carries the printer's LAN credential, and printer credentials never + * rest in the cloud. The gateway verifies them by connecting, stores them + * in its own database, and answers with a `command_result` whose + * `command_id` is `request_id`. **Never log this message.** + * + * No `ca_cert_path` and no serial port on purpose: both name things on the + * gateway's own disk and USB bus, which the cloud does not get to choose. + */ + Type.Object( + { + type: Type.Literal("provision_printer"), + request_id: Type.String(), + printer: Type.Object( + { + /** The gateway's own printer id, chosen by the cloud. */ + id: Type.String({ pattern: "^[A-Za-z0-9_-]{1,64}$" }), + name: Type.String({ minLength: 1, maxLength: 200 }), + vendor: Type.String(), + host: Type.Optional(Type.String({ maxLength: 255 })), + access_code: Type.Optional(Type.String({ maxLength: 128 })), + sn: Type.Optional(Type.String({ maxLength: 64 })), + api_key: Type.Optional(Type.String({ maxLength: 256 })), + }, + { additionalProperties: false }, + ), + }, + { additionalProperties: false }, + ), + /** Forget a printer: leave the running fleet and delete its stored credential. */ + Type.Object( + { + type: Type.Literal("remove_printer"), + request_id: Type.String(), + /** The gateway's own printer id. */ + printer_id: Type.String(), + }, + { additionalProperties: false }, + ), ]); export type EdgeServerMessage = Static; diff --git a/schemas/continuum/v1/edge/server_message.schema.json b/schemas/continuum/v1/edge/server_message.schema.json index 77e087e..d5d0d47 100644 --- a/schemas/continuum/v1/edge/server_message.schema.json +++ b/schemas/continuum/v1/edge/server_message.schema.json @@ -109,6 +109,90 @@ "sdp" ], "additionalProperties": false + }, + { + "type": "object", + "title": "ProvisionPrinter", + "description": "Add a printer to this gateway. Sent by the console through the cloud, which relays it and keeps nothing: it carries the printer's LAN credential (access_code or api_key), and the platform's rule is that those never rest in the cloud. The gateway checks them by connecting to the printer, saves them to its own local store, and answers with a client command_result whose command_id equals request_id. NEVER LOG THIS MESSAGE. Deliberately has no ca_cert_path or serial port: those name things on the gateway's own disk and USB bus, which the cloud does not get to choose.", + "properties": { + "type": { + "const": "provision_printer" + }, + "request_id": { + "type": "string", + "description": "Echoed as command_id in the command_result." + }, + "printer": { + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "^[A-Za-z0-9_-]{1,64}$", + "description": "The gateway's own printer id, chosen by the cloud so that telemetry is reported under an id the cloud already knows." + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 200 + }, + "vendor": { + "type": "string", + "description": "A fleet vendor name: bambu, bambu_v1, bambu_v2, prusa_link, octoprint, klipper." + }, + "host": { + "type": "string", + "maxLength": 255 + }, + "access_code": { + "type": "string", + "maxLength": 128 + }, + "sn": { + "type": "string", + "maxLength": 64 + }, + "api_key": { + "type": "string", + "maxLength": 256 + } + }, + "required": [ + "id", + "name", + "vendor" + ], + "additionalProperties": false + } + }, + "required": [ + "type", + "request_id", + "printer" + ], + "additionalProperties": false + }, + { + "type": "object", + "title": "RemovePrinter", + "description": "Forget a printer on this gateway: drop it from the running fleet and delete its stored credential. Answered with a command_result whose command_id equals request_id.", + "properties": { + "type": { + "const": "remove_printer" + }, + "request_id": { + "type": "string" + }, + "printer_id": { + "type": "string", + "description": "The gateway's own printer id." + } + }, + "required": [ + "type", + "request_id", + "printer_id" + ], + "additionalProperties": false } ] }