# Phase 1.0Y: offline shsrv framing audit Status: `SOURCE_FAMILY_FRAMING_PARTIAL_PROMPT_COMPLETION_UNPROVEN` Date: 2026-07-22 This phase audits only clean, already-local official shsrv Git history and implements a pure host model. It creates no socket, address, live CLI, command formatter or target artifact. No device action occurred. ## Bound source history | Reference | Commit | Framing family | |---|---|---| | v0.7 | `74287f5db6b20320efd7892d7b29cf438fe7cb98` | legacy raw | | v0.8 | `8f76139ee69df4b8cb7c3aee401f05bccb2c2a31` | legacy raw | | v0.9 | `2f2bc5501d40064c18c06f06f7b1f4cab756389b` | libtelnet/NVT introduced | | v0.19/current | `6f320637d56d344a0e7797753099e33238bbf146` | libtelnet/NVT | Commit `2f2bc55` added `libtelnet.c`, `libtelnet.h` and the Telnet state machine to `sh.c`. The current reference is also official tag v0.19. Both local trees are clean. Every local official tag from v0.9 through v0.19 was checked for the same empty option table, NVT flag, send path and `libtelnet.c` presence. These facts identify official source families; they do not identify the deployed binary. ## Byte-flow graph ```text legacy v0.7-v0.8: peer bytes -> socket-backed stdin -> sh_readline stdout/stderr -> socket bytes unchanged v0.9-v0.19: peer bytes -> read(4096) -> telnet_recv/NVT -> pipe -> sh_readline stdout/stderr -> pipe -> read(4096) -> telnet_send_text/NVT -> peer ``` The current server configures an empty Telnet option table and does not call `telnet_negotiate`. It therefore sends no proactive negotiation bytes. From the initial RFC1143 state, received `IAC WILL x` produces `IAC DONT x`, and received `IAC DO x` produces `IAC WONT x`; initial `WONT` and `DONT` produce no reply. A client that sends only plain command bytes triggers none of these replies. ## Exact source-family transformations | Property | legacy raw | libtelnet/NVT | |---|---|---| | incoming plain bytes | unchanged | unchanged except NVT EOL | | incoming CR LF | remains CR LF; CR is later an argument delimiter | becomes LF | | incoming CR NUL | unchanged | becomes CR | | incoming IAC IAC | remains two bytes | becomes one IAC application byte | | outgoing LF | LF | CR LF | | outgoing CR | CR | CR NUL | | outgoing IAC | one IAC | doubled IAC | | proactive negotiation | none | none | | server-side command echo | none in source | none in source | The official host wrapper invokes an external `telnet` program, optionally under `rlwrap`. Local echo, negotiation defaults, chunking and display behavior therefore belong to that external client and are not defined by shsrv. The wrapper has no bounded evidence, sanitization or timeout contract and is not a Chimera client candidate. ## Prompt and completion Both source families use the same control flow: 1. `sh_greet` writes the automatic greeting; 2. `sh_prompt` writes `PWD + "$ "` without a newline and flushes; 3. `sh_readline` waits for LF; 4. `help` completes synchronously, while forked `stat`/`sum` are waited for; 5. all streams are flushed and the loop emits the next prompt. This proves source ordering but not an exact live boundary: - `setenv("PWD", "/", 0)` does not overwrite an inherited `PWD`; - the prompt has no length or prefix field; - arbitrary inherited `PWD` can itself contain the two-byte `$ ` shape; - an external Telnet client's local echo is outside the server contract; - stdout, stderr and negotiation writes can be chunked/interleaved; - current `sh_on_telnet_data` and `sh_on_telnet_send` each use one `write` and only log a short write; they do not finish the remaining bytes; - the exact deployed source family and binary remain unproven. The allowlisted Phase-1.0W path alphabet excludes whitespace, `$`, pipe and shell separators. The audited v0.19 static strings for `help`, `stat` and `sum` contain no `$ ` except `sh_prompt`. This makes a terminal `$ ` a useful source-shaped candidate under that exact source, but not a deployed completion attestation. The offline model therefore never returns `exact_completion_proven=true`. ## Command framing evidence `sh_readline` consumes one byte at a time and ends a command at LF. Both source families therefore accept plain LF termination. In the legacy family, an external Telnet client's preceding CR is removed later by the argument-token delimiter. Multiple already-buffered newline-terminated commands would be processed sequentially by the source loop. No Chimera command-byte formatter is added here. A future passive client contract can avoid Telnet negotiation entirely and use a bounded, prevalidated LF-only batch. That claim remains design-only until separately implemented and tested. ## Robustness and side effects | Finding | Classification | |---|---| | automatic model/serial/firmware/temperature/frequency greeting | `HIGH_FUNCTIONAL_ACCEPTANCE_REQUIRED` | | current single-write handling for pipe and socket | `PROTOCOL_INTEGRITY_RISK` | | no server-side session deadline | `SESSION_HANG_RISK` | | IAC IP/SUSP/ABORT may signal a running child | `HIGH_FUNCTIONAL_EXCLUDED_INPUT` | | legacy Telnet controls pass into the shell byte stream | `PROTOCOL_INTEGRITY_RISK` | | disconnect exits the shell process; outer server can accept again | `SOURCE_DESIGN_ONLY_RUNTIME_UNPROVEN` | | no live filesystem write or autoload in framing model | `SAFE_OFFLINE` | IAC command generation is excluded from every future Chimera plan. The model records synthetic IAC commands so tests cannot silently treat them as text. ## Offline model `tools/phase10y_shsrv_framing_model.py` models both source families with fixed 65,536-byte and 256-chunk limits. It covers NVT EOL, IAC escaping, initial unsupported-option replies, subnegotiation removal and prompt-candidate classification. It has no network import, CLI, target, command sender or file output. Its 22 tests use synthetic bytes only. ## Decision - official framing families: `PROVEN_FROM_LOCAL_OFFICIAL_SOURCE`; - deployed family and binary: `UNPROVEN`; - source prompt order: `PROVEN_FROM_SOURCE`; - terminal `$ ` recognition: `SOURCE_SHAPE_CANDIDATE_ONLY`; - exact live command completion: `UNPROVEN`; - passive no-negotiation approach: `OFFLINE_DESIGN_CANDIDATE`; - live network adapter or collection: `NOT_AUTHORIZED`. The next permitted step is an offline-only passive, source-family-tolerant batch contract. It must retain deadline sealing and partial-result rejection, must never emit Telnet commands, and still may not add a real socket or device address.