- N-1 cut: auth_method_enums! (macro + generated StandardAuthentication/ StandardAuthenticationStarted/allow_no_auth), skip_auth_this_is_not_ rfc_compliant, CheckResult's Option/Result impls (bool stays) — the producer-replaced machinery; ADR-013's no-speculative-surface posture - N-1 keep-notes made current: ConnectError (hand-port companion; the fired trigger + keep disposition recorded in stream.rs), transfer/wait_on_tcp (differential-suite-consumed), Bug (upstream- verbatim, display intact) - N-4: new SocksServerError::Refused(&'static str) — the honest log vocabulary for the five in-stream policy refusal sites (the BIND command gate + dial/egress/bind-factory/bind-accept seams) and the harness's minimal producer; wire bytes untouched (Bug keeps its display; AuthenticationRejected stays the typestate's auth-reject) - Provenance extended, not replaced (convention 17): server.rs module doc's owned-changes paragraph + rfc1928.md's owned-code post-fork changes list + last_updated - Differential :103 comment reworded to the RFC's ordering rationale; AuthMethod doc updated for the macro cut - Tests: refusal-site session-error asserts moved to Refused, the mapping-table loop grew the variant, a display/shape test pins it Verified: cargo test (356 green incl. --all-features), clippy/fmt/doc clean, both wasm checks clean.
10 KiB
id, name, status, depends_on, scope, risk, impact, level
| id | name | status | depends_on | scope | risk | impact | level |
|---|---|---|---|---|---|---|---|
| implementation/fix-rfc1928-posture | Fix — rfc1928 keep-or-cut pass + honest refusal vocabulary (review-002 N-1, N-4) | completed | narrow | medium | component | implementation |
Description
The review-001 keep-or-cut triggers have fired — the producer layer
landed without consuming the anticipated surfaces — and the
in-stream refusal vocabulary mislabels policy refusals as bugs.
One posture pass over both
(docs/reviews/002-protocol-core-implementation-review.md):
-
N-1 (minor) — the fork's consumerless machinery. The producer drives
negotiate_authwith&[NoAuthentication]only; the seams carry their own error vocabularies;pump_bidireplacedtransfer. Per the review's disposition:Cut (the producer already replaced them; ADR-013's no-speculative-surface posture wins):
StandardAuthentication+allow_no_auth+auth_method_enums!'s generated enum (src/rfc1928/server.rs:448-482; the macro itself can stay or go with it — nothing else uses it)skip_auth_this_is_not_rfc_compliant(src/rfc1928/server.rs:185-187; the consumer typestate'sskip_authconfig covers the in-tree need)CheckResult'sOption/Resultimpls (src/rfc1928/server.rs:162-172; keepbool— re-add with a typed-rejection design if a door ever wants it)
Keep with note (the hand-port-map posture, ADR-013):
ConnectError(constructed nowhere, but the hand-port map's companion — its reply-code mapping is what a future port reuses; the module doc already says so)transfer/wait_on_tcp(differential-suite-consumed; their semantics stay pinned)SocksServerError::Bug(now consumed by the producer's refusal sites — see N-4 for its display)
The coverage blocks resolve automatically (the accepted-uncovered posture was exactly these blocks). Update the module docs where they name the cut machinery (e.g.
util/stream.rs'sConnectErrornote, theauth_method_enums!doc's "generate a similar enum" line) and the differential suite's comment that referencesStandardAuthentication's method ordering (tests/rfc1928-differential.rs:103— reword to the RFC's ordering rationale, not the cut type). -
N-4 (observation) — the task-log refusal vocabulary mislabels policy refusals. Five in-stream refusal sites return errors the wire never sees (the wire got its RFC-faithful reply already; these are log/observability signals only), but the vocabulary lies: the BIND command gate returns
SocksServerError::AuthenticationRejected(an ACL refusal is not "authentication rejected" —src/producer.rs:230-233), and four seam refusals returnBug("... refused in-stream")(a policy refusal is not a bug; the display literally saysBUG: ...—src/producer.rs:262-264,302-304,483-485,541-543). An operator greppingBUG:chases ghosts that are working-as-designed refusals.Fix per the review's sketch: add one variant (
SocksServerError::Refused(&'static str)-shaped) for the in-stream seam refusals and the command gate; use it at the five refusal sites. The wire bytes are untouched (these variants never reach the wire — the RFC reply went out first). Alternatively keepBugand rename its display — but the dedicated variant is the honest shape; pick one and record it. Mind the fork's provenance posture (convention 17): this is an owned-code extension, so extend the module doc's carried-changes note if the variant list grows.
Tests: the five refusal sites' existing tests assert the mapped
reply codes (unchanged — the wire is untouched); update any test
asserting the session-error variant at those sites (the harness's
Bug at tests/harness.rs:387 is its own shape — leave unless it
wants the new variant); one test pinning the new variant's
display/shape if the vocabulary is table-tested elsewhere.
Acceptance Criteria
StandardAuthentication,allow_no_auth, the generated enum,skip_auth_this_is_not_rfc_compliant, andCheckResult'sOption/Resultimpls are cut;boolstaysConnectError,transfer/wait_on_tcp,Bugkept — each with its keep-note current (module docs name the posture)- The differential suite stays green (the cut machinery was not
load-bearing for it; the
:103comment reworded) - The five in-stream refusal sites carry the honest vocabulary (one variant or the renamed display — the choice recorded); the wire bytes are untouched (the reply-code assertions stay green)
- The fork's provenance notice is extended, not replaced, if the carried-changes note names the new variant (convention 17)
cargo testgreen; clippy/fmt clean; both wasm checks clean;cargo doc --no-depsclean (module docs changed)
References
- docs/reviews/002-protocol-core-implementation-review.md §N-1, §N-4
- docs/reviews/001-rfc1928-full-review.md (the keep-or-cut triggers this closes out; the C-1 misleading-display note)
- docs/architecture/decisions/013-targeted-fork.md (the hand-port map vs no-speculative-surface distinction)
- docs/architecture/decisions/006-access-control.md (the gate — policy refusals are not authentication failures)
- src/rfc1928/LICENSE (the provenance notice — extend, never replace)
Notes
- N-4 shape chosen: the dedicated variant —
SocksServerError::Refused(&'static str), display"Refused: {0}"— not theBugdisplay rename. The review's sketch favored the dedicated variant ("the honest shape"), and the vocabulary split is real:Bugstays upstream-verbatim (BUG: {0}, its "should be unreachable" contract intact) while policy refusals get their own honest label. The five sites now readRefused("bind command gate: not allowed"),Refused("dial refused in-stream"),Refused("egress refused in-stream"),Refused("bind factory refused in-stream"),Refused("bind accept refused in-stream")— same&'static strpayload shape asBug, zero wire impact (the RFC reply went out before eachErr). - The harness's
Bugsite was migrated too (the task said "leave unless it wants the new variant"):tests/harness.rs's minimal CONNECT producer returnedBug("dial refused in-stream")— the same working-as-designed refusal shape, so it takes the new variant for vocabulary consistency across the log surface. No test asserts that harness error's variant, so nothing else moved. - The mapping-table test grew the new variant:
SocksServerError::Refusedrides theGeneralFailurefall-through loop into_reply_error_mapping_table(alongsideBug), and a new test pins the display string and the fall-through mapping (refused_variant_display_is_honest_and_ wire_invisible) — the task's "one test pinning the new variant's display/shape". - Provenance extended, not replaced (convention 17): the
server.rsmodule doc gained a "Post-fork owned changes" paragraph (the cuts, the keep-notes, theRefusedaddition);docs/architecture/rfc1928.mdgained the matching "owned-code post-fork changes" list under the deliberate modifications and alast_updatedline. The bundledsrc/rfc1928/LICENSEnotice already carries the "modifications after the fork point" clause generically — no change needed there. - Keep-notes made current:
stream.rs'sConnectErrornote records that the trigger fired and the disposition is keep (was: "cut it then");transfer/wait_on_tcp's differential- suite note lives in theserver.rsmodule doc;Bug's keep-note is the same paragraph (upstream-verbatim, its display untouched). - The differential suite's
:103comment reworded to the RFC-ordering rationale (the server picks by its own preference, more-secure-first) — no cut-type reference remains anywhere. - The
AuthMethodtrait doc was updated for the macro cut (upstream's "use enums for sets" line → a custom selection is a slice of method structs) and the module doc's extraction-time adjustments line dropped the#[macro_export]note (the macro itself is gone).
Summary
Both items landed. N-1 (the cut): auth_method_enums! (the
macro, nothing else used it), StandardAuthentication +
StandardAuthenticationStarted + allow_no_auth,
skip_auth_this_is_not_rfc_compliant, and CheckResult's
Option/Result impls are gone from src/rfc1928/server.rs —
the producer-replaced machinery, per ADR-013's
no-speculative-surface posture. Kept with notes: ConnectError
(hand-port companion, stream.rs note updated to record the fired
trigger + keep disposition), transfer/wait_on_tcp
(differential-suite-consumed, semantics pinned there), Bug
(upstream-verbatim, display intact). N-4 (the vocabulary): new
SocksServerError::Refused(&'static str) variant, used at the five
in-stream refusal sites (the BIND command gate + the four seam
refusals) plus the harness's minimal producer; Bug's display is
untouched (a real bug should still read BUG:); the wire bytes are
byte-identical (every reply-code assertion stayed green unchanged).
Tests: the three gate-site session-error asserts moved from
AuthenticationRejected to Refused(...), the four Bug(...)
asserts to Refused(...), the mapping-table loop grew the variant,
and a new display/shape test pins both. Docs: the server.rs
module doc's owned-changes paragraph, the rfc1928.md
"owned-code post-fork changes" list + last_updated, the
stream.rs keep-note, the AuthMethod doc, and the differential
comment. The review-002 N-1 coverage blocks resolve (the cuts were
the accepted-uncovered surface).
Verified: cargo test (356 green across all suites incl.
--all-features), cargo clippy --all-targets -- -D warnings
clean, cargo fmt --check clean, cargo doc --no-deps clean,
cargo check --target wasm32-unknown-unknown +
cargo clippy --target wasm32-unknown-unknown -- -D warnings
clean.