diff --git a/frontend/src/pages/engineering/developer/ApiReferencePage.jsx b/frontend/src/pages/engineering/developer/ApiReferencePage.jsx index 125b5d8..434e80e 100644 --- a/frontend/src/pages/engineering/developer/ApiReferencePage.jsx +++ b/frontend/src/pages/engineering/developer/ApiReferencePage.jsx @@ -677,9 +677,9 @@ const NAMESPACES = [ cmd: 'firmware.status', handler: 'FirmwareHandler', transports: ['All'], - description: 'Get firmware validation state, version, boot count, and commit/rollback eligibility.', + description: 'Get firmware validation state, version, boot count, rollback safety-net diagnostics, and commit/rollback eligibility.', contents: null, - response: '{\n "status": "SUCCESS",\n "type": "firmware.status",\n "data": {\n "validation_state": "VALIDATED",\n "current_version": "143",\n "is_testing": false,\n "is_valid": true,\n "boot_count": 12,\n "build_date": "2026-07-10",\n "ota_channel": "stable",\n "can_commit": false,\n "can_rollback": false\n }\n}', + response: '{\n "status": "SUCCESS",\n "type": "firmware.status",\n "data": {\n "validation_state": "VALIDATED",\n "current_version": "143",\n "is_testing": false,\n "is_valid": true,\n "boot_count": 12,\n "build_date": "2026-07-10",\n "ota_channel": "stable",\n "startup_retry_count": 0,\n "max_startup_retries": 3,\n "runtime_failure_count": 0,\n "max_runtime_failures": 5,\n "backup_version": "142",\n "backup_is_valid": true,\n "can_commit": false,\n "can_rollback": false\n }\n}', errors: [], example: '{ "v": 2, "cmd": "firmware.status" }', warning: null, @@ -951,6 +951,37 @@ const NAMESPACES = [ example: '{ "v": 2, "cmd": "log.get_config" }', warning: null, }, + { + cmd: 'logs.list', + handler: 'LoggingHandler', + transports: ['All'], + description: 'List day-rotated SD log files (/logs/YYYY-MM-DD.log) with size. Requires an SD card.', + contents: null, + response: '{\n "status": "SUCCESS",\n "type": "logs.list",\n "data": {\n "files": [\n { "name": "2026-07-13.log", "size": 48213 },\n { "name": "2026-07-14.log", "size": 9120 }\n ]\n }\n}', + errors: [ + { message: 'SD card not available on this device', condition: 'Device has no SD card, or FileManager was not wired up' }, + ], + example: '{ "v": 2, "cmd": "logs.list" }', + warning: null, + }, + { + cmd: 'logs.download', + handler: 'LoggingHandler', + transports: ['All'], + description: 'Read a bounded chunk (max 4096 bytes) of a log file for offline-device troubleshooting. Loop with the returned next_offset until eof is true.', + contents: [ + { field: 'file', type: 'string', required: true, notes: 'Bare filename as returned by logs.list — no path separators' }, + { field: 'offset', type: 'int', required: false, notes: 'Byte offset to resume from. Default 0.' }, + ], + response: '{\n "status": "SUCCESS",\n "type": "logs.download",\n "data": {\n "file": "2026-07-14.log",\n "data": "[INFO][BellEngine] Ring scheduled (12345ms)\\n",\n "next_offset": 4096,\n "eof": false\n }\n}', + errors: [ + { message: 'SD card not available on this device', condition: 'Device has no SD card, or FileManager was not wired up' }, + { message: 'Missing required field: file', condition: 'contents.file is absent' }, + { message: 'Log file not found: ', condition: 'File does not exist, or file contains a path separator / ".." (rejected)' }, + ], + example: '{ "v": 2, "cmd": "logs.download", "contents": { "file": "2026-07-14.log", "offset": 0 } }', + warning: 'Loop by feeding the previous response\'s next_offset back in as offset until eof is true — a single call never returns a whole large file.', + }, ], }, {