--- id: implementation/core-params-errors name: Core — params schema + scope constants + typed error surface status: pending depends_on: [implementation/core-crate-deps] scope: narrow risk: low impact: component level: implementation --- ## Description Implement `src/params.rs` and `src/error.rs` per wire.md §The Open Op, ADR-001, and ADR-006 — the wire-stable surface (the one-way door) and the typed open-error vocabulary. Template: `/workspace/@alkdev/alktunnels/src/params.rs` (the sibling's spec builder + scope-constant posture). Deliverables: 1. **`src/params.rs`**: - Constants: `OP_SOCKS5_OPEN = "channels/socks5/sub"`, `SOCKS5_ALPN = "alk/socks5"`, `SOCKS5_OPEN_SCOPE = "socks5:open"`, `SOCKS5_BIND_SCOPE = "socks5:bind"` (ADR-001/ ADR-006; the scope-string convention `: `; stable once published). - `socks5_open_spec() -> OperationSpec` — `Sub`-typed, external, channel-open marker on `SOCKS5_ALPN`, **trivial params**: input schema `{type: object}`, `additionalProperties: false` (empty params stay valid forever — ADR-001's additive-only extension rule); reply schema `{"channel_id": integer, minimum 1}`; `required_scopes = ["socks5:open"]`. Follow the alktunnels spec-builder shape exactly (the registry validates against these schemas). - The trivial params struct (`Socks5Params {}` — serde `deny_unknown_fields`, empty) for the consumer's open call. 2. **`src/error.rs`** — the typed open-error surface (alkcall ADR-049 §4): - `SocksOpenError` — the consumer-side open-failure vocabulary mapping the `channel:open_failed` reasons (`dial_failed` / `unknown_resource` / `resource_shortage` / `handler_error` / `timeout`) plus the registry's `FORBIDDEN`/`INVALID_INPUT` classes, shaped on alktunnels' `TunnelOpenError` + `establishment_reason` helper. - The session-level error type for the consumer sessions (`SocksSessionError`-shaped: open errors vs in-stream `SocksError` vs I/O) — the exact variant set is the task's judgment; keep it faithful to what the sessions actually surface (a refused session never yields a phantom channel; a refused target is an RFC reply code surfaced through the session type — consumer.md §Error surface). 3. **lib.rs re-exports** for the new public surface (convention 15). Tests: spec-builder shape assertions (op id, ALPN marker, scopes, schemas — the trivial-params schema rejects unknown fields), params serde round-trip (empty object valid; unknown field rejected), the error-reason mapping table. ## Acceptance Criteria - [ ] Constants + spec builder per ADR-001/ADR-006 exactly (op id, ALPN, both scopes, trivial schemas) - [ ] Input schema rejects unknown fields (the loud-rejection posture) - [ ] Typed open-error surface maps the ADR-049 §4 reasons - [ ] lib.rs re-exports the public surface - [ ] `cargo test` green; clippy/fmt clean; both wasm checks clean ## References - docs/architecture/wire.md §The Open Op (the normative op shape) - docs/architecture/decisions/001-alpn-and-open-op.md (trivial params; the one-way door) - docs/architecture/decisions/006-access-control.md (the two scopes) - docs/architecture/decisions/011-inline-vendor.md §4 (the typed open-error surface) - Template: `/workspace/@alkdev/alktunnels/src/params.rs` (`tunnel_open_spec`, the scope constants, `establishment_reason`) - POC sketch: `/workspace/alksocks-connect-poc/src/params.rs` ## Notes > To be filled by implementation agent ## Summary > To be filled on completion