params/error: the wire-stable open-op surface + the typed open-error vocabulary
- params: the ADR-001/ADR-006 constants (`channels/socks5/sub`,
`alk/socks5`, `socks5:open`, `socks5:bind`), `socks5_open_spec()`
(Sub/External/channel-open marker; trivial empty-object input schema
with loud `additionalProperties: false`; reply
`{channel_id: integer, minimum 1}` required; `socks5:open` scope),
`Socks5Params {}` (deny_unknown_fields — empty stays valid forever),
the `establishment_reason` helper re-export.
- error: `SocksOpenError` (the ADR-049 §4 typed surface, shaped on
alktunnels' `TunnelOpenError`), the typed
`SocksEstablishmentReason` vocabulary (the five reason codes,
parse/as_str; unknown codes never aliased), `SocksOpenError::reason()`
as the typed view, and `SocksSessionError` (open vs in-stream `Rfc`
vs `Io` — a refused target is an RFC reply code through the session
type, consumer.md §Error surface). `SocksError`/`SocksServerError`/
`ReplyError` re-exported from the forked core.
- lib.rs re-exports the new public surface (convention 15).
- 9 new tests: spec shape, constants, serde round-trip +
unknown-field rejection, the reason mapping table, the
non-establishment classes (`FORBIDDEN`/`INVALID_INPUT`/
`too_many_channels`), future-reason non-aliasing, the three-plane
session surface.
- task `implementation/core-params-errors`: status → completed;
Notes + Summary filled.
Verification: cargo test (104 green), clippy --all-targets -D
warnings clean, fmt --check clean, doc --no-deps zero warnings,
both wasm checks (check + clippy on wasm32-unknown-unknown) clean.
This commit is contained in:
1 parent
d530eae5c4
commit
1ccd5bbe0c
4 files changed
+522
-8
No files matched your search
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: implementation/core-params-errors
|
||||
name: Core — params schema + scope constants + typed error surface
|
||||
status: pending
|
||||
status: completed
|
||||
depends_on: [implementation/core-crate-deps]
|
||||
scope: narrow
|
||||
risk: low
|
||||
@@ -81,8 +81,71 @@ error-reason mapping table.
|
||||
|
||||
## Notes
|
||||
|
||||
> To be filled by implementation agent
|
||||
> Filled by the implementation agent (2026-09-23).
|
||||
|
||||
- `src/params.rs`: the four wire-stable constants (`OP_SOCKS5_OPEN`,
|
||||
`SOCKS5_ALPN`, `SOCKS5_OPEN_SCOPE`, `SOCKS5_BIND_SCOPE`), the
|
||||
trivial-params struct `Socks5Params {}` (serde
|
||||
`deny_unknown_fields`, + `Serialize` so tests round-trip it;
|
||||
`as_json()` names the canonical wire form), `socks5_open_spec()`
|
||||
(Sub/External/channel-open marker on `alk/socks5`; input schema
|
||||
`{type: object, additionalProperties: false}`; reply schema
|
||||
`channel_id` integer minimum 1 required; `required_scopes =
|
||||
["socks5:open"]`), and the `establishment_reason` helper re-export
|
||||
(the alktunnels posture — delegates to
|
||||
`ChannelOpenError::establishment_reason`).
|
||||
- `src/error.rs`: `SocksOpenError` (single `Open` variant wrapping
|
||||
`ChannelOpenError` — the same shape as alktunnels'
|
||||
`TunnelOpenError`; the `From` impl covers the
|
||||
`channel:open_failed`/`FORBIDDEN`/`INVALID_INPUT` classes), the
|
||||
typed `SocksEstablishmentReason` vocabulary (ADR-049 §3's five
|
||||
codes, `parse`/`as_str`; unknown codes are `None` — never silently
|
||||
aliased, the vocabulary is one-way), `SocksOpenError::reason()` as
|
||||
the typed view, and `SocksSessionError` (open errors vs in-stream
|
||||
`Rfc(SocksError)` vs `Io`; the RFC reply-code refusals ride the
|
||||
session type per consumer.md §Error surface). `SocksError`/
|
||||
`SocksServerError`/`ReplyError` re-exported from `rfc1928`
|
||||
(`SocksServerError` lives in `rfc1928::server`, not the module
|
||||
root).
|
||||
- lib.rs re-exports both modules' public surface (convention 15).
|
||||
- Deliberate deviations from the task text: the params struct
|
||||
derives `Serialize` (test round-trip needs it; harmless on the
|
||||
wire — the consumer sends `json!({})`); `SocksEstablishmentReason`
|
||||
is a separate named type rather than an inline match so the
|
||||
mapping table is testable in both directions; unknown reason codes
|
||||
do NOT alias a variant (one-way vocabulary discipline).
|
||||
- rustdoc links to `error::SocksOpenError` from `params` are
|
||||
fully-qualified (`crate::error::…`) — plain `[SocksOpenError]`
|
||||
does not resolve cross-module in this crate's layout.
|
||||
|
||||
## Summary
|
||||
|
||||
> To be filled on completion
|
||||
> Filled on completion (2026-09-23).
|
||||
|
||||
Implemented the wire-stable open-op surface and the typed
|
||||
open-error vocabulary:
|
||||
|
||||
- `params`: constants + `socks5_open_spec()` per ADR-001/ADR-006
|
||||
exactly (op id `channels/socks5/sub`, ALPN `alk/socks5`, scopes
|
||||
`socks5:open`/`socks5:bind`, trivial empty-object input schema with
|
||||
loud `additionalProperties: false`, reply
|
||||
`{channel_id: integer, minimum 1}` required).
|
||||
- `Socks5Params {}` with `deny_unknown_fields` — empty object valid,
|
||||
unknown fields rejected.
|
||||
- `error`: `SocksOpenError` mapping the ADR-049 §4 reasons
|
||||
(`dial_failed`/`unknown_resource`/`resource_shortage`/
|
||||
`handler_error`/`timeout`) through the typed
|
||||
`SocksEstablishmentReason` (unknown codes never aliased); the
|
||||
registry's `FORBIDDEN`/`INVALID_INPUT` classes correctly
|
||||
non-establishment; `SocksSessionError` shaped open-vs-Rfc-vs-Io
|
||||
per consumer.md §Error surface.
|
||||
- 9 new tests (spec shape, constants, serde round-trip + unknown-field
|
||||
rejection, the reason mapping table, non-establishment classes,
|
||||
future-reason non-aliasing, the three-plane session surface).
|
||||
- lib.rs re-exports the public surface.
|
||||
|
||||
Verification: `cargo test` (104 green: 67 lib + 37 rfc1928 + 0
|
||||
doc), `cargo clippy --all-targets -- -D warnings` clean,
|
||||
`cargo fmt --check` clean, `cargo doc --no-deps` zero warnings, both
|
||||
wasm checks (`cargo check` + `cargo clippy` on
|
||||
`wasm32-unknown-unknown`) clean.
|
||||
Reference in new issue
Block a user