26 KiB
Implementation roadmap
This document tracks the implementation and hardware-validation plan for the ESP32 Serial Swiss Army Knife. It describes intended sequencing rather than a release schedule. A phase is complete only when its implementation, documentation, build validation, and relevant hardware tests have passed.
Status legend
- Complete — implemented and validated on the target hardware.
- In progress — implementation or validation is actively underway, but the overall phase is not complete.
- Implemented; validation pending — code is present and builds, but the current implementation still needs the listed hardware checks.
- Planned — accepted project direction, not yet implemented.
- Under evaluation — useful candidate whose feasibility, security, or resource cost must be measured before it becomes a commitment.
Project-wide design constraints
These constraints apply across all phases:
- UART0 remains the trusted physical administration and recovery console.
- UART1 and the MAX3243 provide the single physical RS-232 data port.
- All serial transports use the central session broker: one writer, multiple observers.
- A slow or failed client must not block UART reception or unrelated clients.
- Serial data paths remain binary-transparent; transports must not reserve in-band control sequences.
- Network serial access must be authenticated and encrypted. No unauthenticated plaintext TCP serial service is planned.
- Secrets must not be exposed by routine status output, command completion, or logs.
- Resource use must remain bounded and observable on the ESP32-S3 N16R8 target.
- New work must preserve USB CDC and UART0 recovery when Wi-Fi or a network service fails.
- Project code remains
GPL-3.0-only; third-party license notices and compatibility must be preserved.
Phase overview
| Phase | Scope | Status |
|---|---|---|
| 0 | RS-232 hardware characterization and diagnostics | Complete |
| 1 | Persistent UART1 serial-service foundation | Complete |
| 2 | Transport-neutral session broker | Complete |
| 3 | Native USB CDC-ACM serial transport | Complete |
| 4 | Wi-Fi station/AP foundation and network diagnostics | Complete |
| 5A | Authenticated HTTPS administration foundation | Complete |
| 5B | Offline xterm.js WebSocket serial terminal | Complete |
| 6 | Authenticated SSH serial transport | Complete |
| 7 | Local display and button interface | In progress (7E validation) |
| 8 | Security and production hardening | Planned |
| 9 | Authenticated, rollback-capable OTA | Planned |
| 10 | BLE serial transport and provisioning evaluation | Planned |
| 11 | Advanced network integration | Under evaluation |
| 12 | Optional filesystem-backed features | Under evaluation |
Completed foundation
Phase 0 — RS-232 hardware characterization
Implemented and hardware-validated:
- Central board pin profile for the ESP32-S3 N16R8 and MAX3243 breakout.
- MAX3243 enable, static driver, receiver, valid-voltage, and modem-signal checks.
- UART loopback across supported framing and baud-rate combinations.
- Hardware CTS transmit gating and RTS receive-backpressure tests.
- Exclusive RS-232 port ownership and fault-safe cleanup.
- RGB status indication for diagnostic state.
- Potentially disruptive tests isolated under the
debugCLI submenu; top-levelstatusretained.
Detailed procedures are in Electrical tests and Hardware wiring.
Phase 1 — Serial-service foundation
Implemented and hardware-validated:
- Persistent, versioned UART configuration with safe defaults.
- UART1 lifecycle management and exclusive ownership.
- Nonblocking RX and TX software streams.
- Baud rate, data bits, parity, stop bits, RTS/CTS, DTR policy, and RTS threshold controls.
- Runtime counters and safe restart after working-configuration changes.
- Explicit save/load/default/reset behavior; edits are not silently persisted.
Phase 2 — Session broker
Implemented and hardware-validated:
- Up to eight generation-safe broker clients.
- Exactly one writer lease with multiple observers.
- Bounded per-client output and event queues.
- Slow-observer isolation and drop accounting.
- Writer grant, release, denial, revocation, and forced administrative reassignment.
- DTR
on-connectintegration. - Partial-transfer and retryable no-progress semantics for transports.
- Broker payload storage placed preferentially in PSRAM while FreeRTOS control structures remain in internal RAM.
Phase 3 — Native USB CDC-ACM
Implemented and hardware-validated:
- Native ESP32-S3 USB CDC-ACM serial transport.
- Automatic broker connection when the host opens the port with DTR asserted.
- Opportunistic writer acquisition with observer fallback.
- Binary-transparent bidirectional serial data.
- Supported host line-coding application while USB owns the writer lease.
- Disconnect cleanup, bounded buffering, counters, and UART0 lifecycle controls.
Phase 4 — Wi-Fi foundation
Implemented and hardware-validated:
- Four persistent station profiles with priority ordering.
- WPA2/WPA3 mixed mode and WPA3-SAE-required mode.
- Explicit no-echo secret entry through UART0.
- AP policies
off,fallback, andalways. - Random persistent fallback-AP password and MAC-derived default SSID.
- Bounded profile attempts, DHCP deadlines, failover, and retry backoff.
- Root and
wifialiases forping,nslookup, andtraceroute. - Wi-Fi/lwIP payload allocation configured to prefer PSRAM with capacities pinned in
sdkconfig.defaults.
A WPA3-required profile correctly rejects an AP that does not advertise the required Protected Management Frame capability; mixed mode is the compatible choice for such an AP.
Phase 5A — Authenticated HTTPS foundation
Implemented and hardware-validated:
- HTTPS-only service on TCP port 443 using ESP-IDF mbedTLS.
- Persistent random shared
admincredential. - Persistent device-specific ECDSA P-256 certificate and private key.
- Physical-console credential retrieval, rotation, certificate inspection, rotation, and recovery.
- Explicit failure behavior that preserves UART0, USB, serial, and Wi-Fi recovery paths.
- Credential rotation revocation hooks shared with WebSocket and SSH sessions.
Phase 5B — Offline browser terminal
Implemented and hardware-validated:
- Vendored xterm.js and FitAddon assets; no Internet or CDN dependency.
- CSP-compatible page structure with scripts served as separate resources.
- Authenticated status and one-time WebSocket-ticket APIs.
- Binary WebSocket serial frames and broker writer/observer integration.
- Two bounded browser-terminal sessions.
- Writer request/release controls and role indication.
- Bounded TLS/socket behavior and slow-observer isolation.
- Viewport-constrained terminal fitting without recursive page growth.
- Validation with multiple clients, ANSI colors, advanced escape sequences, and full-screen terminal software.
Latest completed phase
Phase 6 — Authenticated SSH serial transport
The SSH implementation is complete and hardware-validated. It provides:
- wolfSSH on TCP port 22 while HTTPS remains on mbedTLS.
- Password authentication using the shared
admincredential. - A separate persistent ECDSA P-256 SSH host key and OpenSSH-compatible fingerprint.
- Interactive shell/PTY channels only.
- No
exec, subsystem, SFTP, SCP, agent forwarding, or TCP forwarding. - Two fixed session/handshake slots.
- Three password attempts and a 15-second handshake deadline.
- No broker client before successful authentication and shell negotiation.
- Binary-transparent serial forwarding with no in-band writer-control protocol.
- Opportunistic writer acquisition and observer behavior through the common broker.
- Credential-rotation revocation and UART0 session/host-key administration.
- A single bounded wolfSSH owner task pinned to CPU 1.
- wolfSSL/wolfSSH allocations that prefer PSRAM with internal-memory fallback.
- A per-call wolfSSH receive budget to prevent pipelined input from monopolizing the owner task.
- Bounded broker and WebSocket work bursts that guarantee scheduler/idle progress during sustained serial traffic.
- Software AES for PSRAM-backed mbedTLS records plus software wolfCrypt AES/SHA, preventing mbedTLS and wolfSSL from independently reconfiguring shared ESP32 crypto hardware.
- Internal task stacks retained for safety during flash/NVS cache-disable windows.
- Heap and SSH stack telemetry through
memoryandssh status.
SSH login, host-key verification, serial traffic, Web Serial coexistence, and USB CDC coexistence have been validated. During concurrency testing, the previously failing three-client arrangement used USB CDC and SSH as writer in turn while the remaining transports observed.
Early runs showed healthy heap values but CPU 0 idle-task watchdog timeouts, disproving the initial memory-pressure hypothesis. One trace exposed an unbounded broker scheduling path. A later, decisive trace repeatedly stopped inside mbedTLS's external-RAM hardware-AES DMA wait while HTTPD encrypted a WebSocket record. The broker and WebSocket producer now use bounded active bursts, mbedTLS software AES avoids the hanging PSRAM DMA path, and wolfSSL AES/SHA hardware acceleration is disabled because its private locks do not coordinate with ESP-IDF's crypto lock.
Phase 6 hardware validation
The final target-hardware retest covered:
- USB CDC, one WebSocket terminal, and one SSH terminal connected concurrently.
- SSH as writer with USB CDC and WebSocket observing.
- USB CDC as writer with SSH and WebSocket observing.
- Serial traffic with active readers and writer-token release/reassignment.
- Continued HTTPS/WebSocket, SSH, USB CDC, serial-service, and UART0 responsiveness.
The software-crypto build no longer reproduces the HTTPD watchdog stall. This validates that the failure was a shared hardware-crypto/PSRAM DMA problem rather than heap exhaustion. Phase 6 is complete; these concurrent arrangements remain regression tests for future transport, TLS, memory-placement, and ESP-IDF changes.
Current and planned phases
The order below is the current plan. Phase 7 is in progress; later phases remain planned or under evaluation. Detailed requirements should be finalized at the start of each phase, and optional features must not weaken the completed serial and recovery paths.
Phase 7 — Local display and buttons
Add a standalone local status/control interface without making it a dependency of the serial core. The planning baseline uses a 128×64 dual-color monochrome I²C OLED sold with an SSD1315 controller. Phase 7A confirmed SSD1306-compatible operation, 7-bit I²C address 0x3c, orientation, column mapping, contrast/inversion behavior, button inputs, and the physical color geometry on the selected hardware.
Phase 7A diagnostics and target-hardware electrical validation are complete. Phases 7B, 7C, and 7D are complete. Phase 7E is implemented and awaiting target-hardware fault and persistence validation.
Hardware baseline
- Wire OLED
VCCto3V3and OLEDGNDtoGND. The OLED must use 3.3 V because module-mounted I²C pull-ups may connect SDA and SCL toVCC. - Wire OLED
SDAto GPIO11 and OLEDSCLto GPIO12. These pins are currently unused and sit in the available GPIO10–14 block on the DevKit header. - Wire three active-low buttons between their GPIO and
GND, using the ESP32 internal pull-ups: GPIO10 for previous/back, GPIO13 for select/confirm, and GPIO14 for next. - Use short left/right presses for page or item navigation, short select for entry, a long left press for back/home, and an explicit select hold for disruptive confirmation.
- Verify whether the module provides suitable SDA/SCL pull-ups and that every external pull-up is tied to 3.3 V, not 5 V; add external pull-ups to 3.3 V if the module does not provide them.
- Hardware verification established yellow rows 0–15 and blue rows 16–63. A narrow physical black divider separates the two regions even though row 15 is the final yellow addressable row and row 16 the first blue addressable row.
- Keep assignments centralized in the board profile rather than scattering display or button GPIO assumptions through UI code.
The persistent yellow strip uses fixed-position serial, Wi-Fi-strength, USB, WebSocket, SSH, broker-client, and alert icons. Active icons are solid with a compact value below; inactive icon slots remain blank and show no value. The blue 128×48 content panel begins at row 16 and rotates through overview, RS-232, broker-client, and network/service pages; the physical black divider remains visually clear. No password, Wi-Fi secret, private-key material, or routine credential data may appear on the display.
Implementation sequence
- Phase 7A — Electrical bring-up and diagnostics — Complete
- Bounded low-level display and button diagnostics are available under the existing
debugsubmenu. - The selected module acknowledged at 7-bit
0x3c(8-bit0x78write /0x79read). A guarded full scan is retained for the dedicated local-UI bus; an absent display remains nonfatal and does not make the serial core dependent on the OLED. - Hardware validation passed for geometry, orientation, row/column addressing, contrast, inversion, button pull-ups/debounce/short-press/long-press/stuck behavior, and the color geometry: yellow rows 0–15, blue rows 16–63, with a physical black separator between the regions.
- Bounded low-level display and button diagnostics are available under the existing
- Phase 7B — Display driver — Complete
- The
local_displayservice owns the local I²C bus, SSD1315-compatible panel, and framebuffer. It uses a static 1 KiB 128×64 framebuffer, a compact 5×7 upper/lowercase, digit, and punctuation renderer, and an internal mutex; do not add LVGL for this fixed monochrome UI. - Rendering treats the yellow 128×16 status panel (rows 0–15) and blue 128×48 content panel (rows 16–63) as separate panels so the physical divider remains clear.
- Frame commits refresh only dirty 8-pixel pages. I²C runs at 100 kHz with bounded transactions.
- The display bus initializes at boot; a known display is automatically initialized and cleared. A missing or unresponsive display is nonfatal and does not make the serial core dependent on it.
- Target-hardware validation passed for initialization, all display diagnostic patterns, the rendered panel layout and physical divider, row 15/16 boundary, contrast, inversion, display-off/reinitialization, and button diagnostics. Observed contrast control has a useful brightness range of 1–255.
- The
- Phase 7C — Read-only status UI — Complete
- The low-priority
local_status_uiowner task builds display state from copied public serial, Wi-Fi, broker, USB, WebSocket, HTTPS, and SSH snapshots. It does not parse CLI output, reach into transport internals, or become a broker client. - Previous/back and next short presses navigate overview, RS-232/modem, broker-client/writer, and network/service pages. Select has no state-changing action in this read-only phase.
- The task polls and debounces the existing active-low button inputs and refreshes at 4 Hz maximum. It collects service snapshots before beginning a display frame, so no service or broker lock is held across an I²C transaction.
- The yellow panel is page-independent and uses fixed icon slots. Wi-Fi strength is shown by segmented Wi-Fi bars; the USB glyph is derived from Pictogrammers Material Design Icons. Page text uses lowercase where appropriate, separates labels and values with colons, and shows the active station or AP SSID plus channel.
- To reduce OLED aging, inactivity dims contrast to
1after five minutes and switches the panel off after ten minutes. The first debounced button press restores contrast127and wakes without navigating. - A missing/unresponsive display is nonfatal; the task remains read-only and never acquires serial writer ownership.
- Target-hardware validation passed for the four pages, fixed active-only status icons, lowercase layout, diagnostics hold, dim/off/wake behavior, all available concurrent client interfaces, UART0 recovery, and serial traffic from 9600 through 230400 baud.
- The low-priority
- Phase 7D — Local controls — Complete
- A shallow local
Controlsmenu directly invokes public serial-service, Wi-Fi, HTTPS, SSH, broker, display, and restart APIs; it never parses or injects CLI text. - The menu provides serial start/stop, Wi-Fi start/stop/reconnect/next-profile, HTTPS start/stop, SSH start/stop, emergency current-writer revocation, display off, and reboot.
WiFi:next profilequeues a rotation to the enabled profile after the currently active one in priority order, wrapping safely; profile configuration and credentials remain unavailable to the UI. The menu deliberately excludes serial configuration editing, Wi-Fi profile/AP changes, host-key/certificate changes, I²C scans, and assignment of the writer to another client. - A visible confirmation screen and one continuous two-second Select hold are required for service stops, Wi-Fi reconnect, Wi-Fi next-profile, writer revocation, and reboot. The confirmation times out after 30 seconds; previous/back cancels. A wake press is consumed and cannot navigate or confirm an action.
- Wi-Fi lifecycle results report a queued request rather than falsely claiming an asynchronous transition has completed. HTTPS/SSH start requests require a connected station or active AP. The current writer is only ever force-released to no writer; the UI is not a broker client and cannot acquire or assign a writer lease.
- Target-hardware validation passed for menu navigation and timeout behavior, controls and asynchronous results, two-second confirmations and cancellation, Wi-Fi next-profile progression/wrap, chord rejection, wake-press suppression, and preservation of UART0 plus transport recovery.
- A shallow local
- Phase 7E — Reliability, persistence, and documentation — Implemented; validation pending
- At startup, a bounded five-second OLED-only identity animation renders a compact monochrome, right-oriented derivative of the project logo in the blue panel: its upright
>_terminal remains readable, while both USB and serial cable ends enter from the left. The full device name scrolls through the yellow panel. A missing or failing OLED skips the animation without delaying recovery services further. - A versioned
local_uiNVS configuration makes the dim and display-off inactivity delays independently configurable from 0 through 86400 seconds. Zero disables a transition; defaults remain 300/600 seconds. UART0displaycommands provide status, RAM edits, save/load, defaults, and atomic reset behavior. - A button held for ten seconds is quarantined until its debounced release, after which it rearms. Quarantined inputs no longer keep a chord latched or block the other controls. A confirmation hold can execute at most once.
- Dim/off wake and missing-display recovery now occur only on a new debounced press edge. A held or stuck input cannot continuously probe an absent OLED, flood logs, or indefinitely refresh the inactivity timer; the wake gesture remains consumed.
- Dirty framebuffer commits have a 500 ms scheduling budget in addition to each bounded 250 ms I²C transaction. A failed frame marks the panel unavailable, while serial, broker, network, USB, and UART0 services remain independent. Safely reconnecting the OLED and pressing a button requests one bounded reprobe.
- Wi-Fi manager queue drops now activate the persistent yellow alert slot and remain observable through Wi-Fi counters. Local action errors continue to be reported directly without blocking queue insertion.
- Pending target-hardware validation: configuration persistence/disable semantics, absent and reattached display behavior, I²C NACK/timeout handling, each stuck button and rearm path, repeated actions/queue-error indication, and concurrent USB CDC, WebSocket, SSH, serial, and UART0 operation during faults.
- At startup, a bounded five-second OLED-only identity animation renders a compact monochrome, right-oriented derivative of the project logo in the blue panel: its upright
Completion requires electrical validation on the selected module, correct operation with all current transports, bounded display/button failure behavior, safe action confirmation, no unexplained serial or broker loss, and documented UART0 recovery.
Phase 8 — Security and production hardening
Harden stored credentials, boot integrity, update trust, failure diagnostics, and dependency maintenance. This phase must be staged carefully because some ESP32 eFuse operations are irreversible.
Planned work:
- Define development, test, and production security profiles.
- Enable and validate NVS encryption for Wi-Fi, HTTPS, and SSH material.
- Evaluate flash encryption and PSRAM encryption for the target hardware and threat model.
- Enable secure boot with a documented signing-key and recovery process.
- Define secret-safe core-dump handling; do not expose credentials or session material in diagnostics.
- Audit key and session-material zeroization across application, mbedTLS, wolfSSL, and wolfSSH allocations.
- Add authentication throttling, lockout/backoff, and security-event counters where appropriate.
- Review TLS/SSH algorithms, certificate policy, password policy, and browser security headers.
- Review current wolfSSL/wolfSSH and ESP-IDF security releases instead of treating integration versions as permanent pins.
- Recheck all third-party licenses and preserve source/license notices.
- Document provisioning, key rotation, factory reset, backup, recovery, and device decommissioning.
Security features must be validated first on expendable hardware before any irreversible production configuration is recommended.
Phase 9 — Authenticated OTA and rollback
Use the existing dual 4 MiB application slots and otadata partition to add safe firmware updates.
Planned work:
- Accept only authenticated, integrity-checked firmware images compatible with the selected secure-boot policy.
- Support an update path that does not expose a plaintext management endpoint.
- Stream downloads with bounded RAM use and explicit progress/error reporting.
- Preserve serial, Wi-Fi, HTTPS, and SSH configuration across successful updates.
- Mark new firmware pending until a post-boot health check succeeds.
- Roll back automatically after failed boot or health confirmation.
- Define power-loss behavior for every update stage.
- Keep UART0 recovery and wired re-flashing documented and functional.
- Add version/compatibility checks and reject accidental downgrade unless an explicit policy allows it.
OTA is complete only after successful update, interrupted-update, invalid-image, rollback, and configuration-persistence tests on hardware.
Phase 10 — BLE
Evaluate and, if resource limits permit, add BLE as another bounded transport or provisioning path.
Planned work:
- Decide whether BLE is primarily a serial transport, a provisioning interface, or both.
- Require authenticated pairing/bonding appropriate to the device threat model.
- Integrate serial access through the existing broker rather than bypassing writer ownership.
- Preserve binary transparency through explicit framing and MTU-aware partial transfers.
- Bound connections, queues, retries, and advertising behavior.
- Measure coexistence with 2.4 GHz Wi-Fi, HTTPS, WebSocket, SSH, USB CDC, and UART service.
- Store bond/provisioning data under the hardened secret-storage policy.
- Provide UART0 controls and a physical recovery path for clearing BLE state.
BLE remains subordinate to stable Wi-Fi and serial operation; it should be omitted if coexistence or memory costs cannot be bounded acceptably.
Phase 11 — Advanced network integration
These features are candidates, not current commitments:
- mDNS advertisement for the certificate’s device-specific
.localname and selected services. - Enterprise Wi-Fi support, subject to credential-storage and certificate-validation design.
- IPv6 behavior and diagnostics beyond the current basic support.
- WireGuard feasibility evaluation, including RAM, CPU, licensing, key storage, routing, and recovery impact.
The device is not intended to become a general-purpose router. Captive-portal interception, unauthenticated DNS redirection, NAPT, and a plaintext serial listener remain out of scope unless the project requirements are explicitly revised.
Phase 12 — Optional filesystem-backed features
The storage partition is reserved but not currently mounted. Possible uses must be justified individually:
- LittleFS-backed web assets to decouple large static files from the application image.
- Bounded diagnostic logs with explicit retention and secret-redaction rules.
- Import/export of non-secret configuration.
- Optional user files needed by later administration features.
Before enabling storage, define corruption recovery, wear limits, quotas, atomic update behavior, compatibility across OTA slots, and whether encryption is required. Serial operation and recovery must not depend on a mountable filesystem.
Cross-phase release gates
Every phase should satisfy the following before being marked complete:
- A clean release build for the ESP32-S3 N16R8 target.
- No new compiler or project diagnostics attributable to the change.
- Focused automated tests where practical and documented hardware tests where hardware behavior is involved.
- UART0, native USB CDC, and previously completed network transports still operate.
- Broker writer/observer semantics and binary transparency remain intact.
- Failure, disconnect, stop/start, reboot, and stale-session cleanup paths are exercised.
- Runtime memory, stack, socket, and queue bounds are measured under maximum supported concurrency.
- Secrets remain absent from ordinary status output and logs.
- Command reference, Hardware wiring, electrical tests, and this roadmap are updated as applicable.
- New dependencies receive security, maintenance, and GPL-3.0 compatibility review.
Explicitly deferred work
The following are not implemented merely because flash partitions or library support exist:
- NVS, flash, or PSRAM encryption.
- Secure boot or production eFuse provisioning.
- OTA download, image confirmation, or rollback policy.
- Core-dump collection or secret-safe core-dump processing.
- Filesystem mounting.
- Public-key SSH user authentication.
- SFTP, SCP, SSH
exec, forwarding, or subsystems. - General routing, NAPT, captive-portal interception, or unauthenticated serial access.
Deferring these features is intentional: each changes the security model, recovery behavior, or bounded-resource assumptions and therefore requires its own design and validation gate.