# Phase 12 SSH listener regression Run `python3 tests/ssh_phase12/run.py` from the repository root. Requires Python 3 and a host C compiler (`cc`). It extracts the production functions without rewriting them and compiles with `-std=c11 -Wall -Wextra -Werror`. Coverage: - One AF_INET6/TCP wildcard listener, explicitly checked IPV6_V6ONLY=0 before bind. - Failures at socket, dual-stack option, bind, listen and both nonblocking steps: no published descriptor, exactly one close after socket allocation. - Permanent accept errors withdraw availability, invalidate the service generation without wrap, and request owner-side session cleanup; temporary errors retain the listener. Capacity rejection respects the existing four-accept budget. - IPv4, global IPv6, scoped link-local IPv6, mapped IPv4, maximum numeric scope, unknown families, and bounded/truncated peer formatting. `tests/ssh_management/runtime.py` additionally tests availability across real production start/stop functions with context/listener/cleanup doubles, including failed session cleanup retaining the context, successful restart, and failed start. Existing management/security regressions remain responsible for authentication, identity ownership and generation fencing. ## SDK contract checked during implementation Read-only inspection of installed ESP-IDF **5.5.0** (`framework-espidf@3.50500.0`, not the separately installed 5.5.3): - `components/lwip/lwip/src/include/lwip/sockets.h`: `sockaddr_in6.sin6_scope_id` is `u32_t`; `IPV6_V6ONLY` is supported. - `components/lwip/lwip/src/include/lwip/inet.h`: `IN6ADDR_ANY_INIT`. - `components/lwip/lwip/src/api/sockets.c`: `lwip_setsockopt_impl` applies `netconn_set_ipv6only`; `IP6ADDR_PORT_TO_SOCKADDR` copies the interface zone; `lwip_accept` publishes the peer address and maps a closed listener to EINVAL, non-TCP sockets to EOPNOTSUPP, and descriptor exhaustion to ENFILE. - `components/lwip/lwip/src/api/api_msg.c`: wildcard IPv6 bind/listen with V6ONLY disabled selects `IPADDR_TYPE_ANY`, accepting both families on one listener. These host doubles do **not** execute lwIP, actual networking, wolfSSH handshakes, RTOS concurrency, discovery traffic or hardware. No PlatformIO build is required or claimed. Device follow-up must verify IPv4-only, IPv6-only and dual-stack connections, scoped link-local access, address changes/reconnects, simultaneous clients and binary UART traffic, advertisement convergence after start/stop/error, and independent UART0/native USB recovery. ## Resource and handoff notes No extra socket, task, session, queue, I/O buffer or heap allocation is introduced. Peer arrays grow from 48 to 65 bytes: 68 additional raw bytes across the two owner slots and two published snapshots, plus ABI padding. Public snapshot copies also grow. Exact linked RAM/flash and stack headroom were not measured without a target build; host tests do not establish ESP32 memory headroom. Project agent memory is intentionally not edited under the exclusive-write scope. The parent should record the one-socket dual-stack contract, scoped peer capacity, and owner-driven mDNS availability (eventual Wi-Fi-manager reconciliation) in the relevant durable memory when integrating Phase 12.