feat: crate-init — module skeleton (params, wire, producer, consumer, error)
- src/{params,wire,producer,consumer,error}.rs skeletons with module
docs per overview.md §Module Map; lib.rs crate docs + re-exports
- constants in params.rs (OP_TUNNEL_OPEN, TUNNEL_ALPN,
TUNNEL_OPEN_SCOPE) + establishment_reason helper (delegates to
alkcall 0.7.0's ChannelOpenError::establishment_reason)
- MAX_DATAGRAM_LEN (65535) in wire.rs (ADR-003's frame-time bound)
- async-trait dropped: skeleton confirms no trait (ADR-004)
Verified: cargo check, clippy --all-targets -D warnings (native +
wasm32), fmt --check, test, wasm32 check — all clean
This commit is contained in:
Generated
-1
@@ -51,7 +51,6 @@ name = "alktunnels"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"alkcall",
|
"alkcall",
|
||||||
"async-trait",
|
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures",
|
"futures",
|
||||||
"serde",
|
"serde",
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ bytes = "1"
|
|||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
async-trait = "0.1"
|
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
thiserror = "2"
|
thiserror = "2"
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
//! The consumer half: `TunnelSession` — the typed client for tunnel
|
||||||
|
//! channels (ADR-005). Forward path (`open`), reverse path (`adopt`),
|
||||||
|
//! substrate-shaped data planes (`stream_halves` / `take_halves` /
|
||||||
|
//! `send_datagram` / `recv_datagram`), and teardown ownership
|
||||||
|
//! (`close` / `join` / `Drop`).
|
||||||
|
//!
|
||||||
|
//! Skeleton module — filled by `tunnels/consumer-session`.
|
||||||
|
|
||||||
|
pub use crate::producer::{OP_TUNNEL_OPEN, TUNNEL_ALPN};
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
//! Tunnel error surfaces: the crate's `TunnelError` plus the typed
|
||||||
|
//! open-error helpers consumers branch on (ADR-049 §4 surface).
|
||||||
|
//!
|
||||||
|
//! Skeleton module — filled by `tunnels/params` (codec + establishment
|
||||||
|
//! error mapping) and `tunnels/consumer-session` (session errors).
|
||||||
|
|
||||||
|
/// The crate-level error type (thiserror; AGENTS.md convention 2).
|
||||||
|
///
|
||||||
|
/// Skeleton: the codec and session variants land with
|
||||||
|
/// `tunnels/wire-codec` and `tunnels/consumer-session`.
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
pub enum TunnelError {
|
||||||
|
/// The data-plane codec rejected an operation (UDP framing).
|
||||||
|
#[error("codec: {0}")]
|
||||||
|
Codec(String),
|
||||||
|
/// A substrate-shaped operation was attempted on the wrong
|
||||||
|
/// data plane (e.g. `send_datagram` on a stream tunnel).
|
||||||
|
#[error("wrong substrate for this operation")]
|
||||||
|
WrongSubstrate,
|
||||||
|
/// An I/O failure on the session's data plane.
|
||||||
|
#[error("io: {0}")]
|
||||||
|
Io(#[from] std::io::Error),
|
||||||
|
}
|
||||||
+27
-3
@@ -1,5 +1,29 @@
|
|||||||
//! alktunnels — arbitrary bidirectional tunnels over alkcall channels.
|
//! alktunnels — arbitrary bidirectional tunnels over alkcall channels.
|
||||||
//!
|
//!
|
||||||
//! Protocol-only scaffold. The producer half (tunnel open-handler),
|
//! TCP, UDP, unix-socket, and other stream/datagram substrates, in the
|
||||||
//! consumer half (typed session), and shared wire/target-addressing
|
//! `ssh -L` / `ssh -D` / `ssh -R` sense. A producer/consumer protocol
|
||||||
//! modules land with the Phase 1 architecture spec.
|
//! crate riding alkcall channels the same way alktty does (`alk/tty`
|
||||||
|
//! is the sibling precedent): the producer half registers the
|
||||||
|
//! `alk/tunnel` open op and pumps bytes between the channel and the
|
||||||
|
//! substrate; the consumer half is the typed session
|
||||||
|
//! ([`TunnelSession`]) that opens tunnel channels and owns teardown.
|
||||||
|
//!
|
||||||
|
//! A tunnel is a resource, not an address: the open-op params identify
|
||||||
|
//! a produced resource + substrate ([`TunnelParams`], ADR-001); the
|
||||||
|
//! producer owns the backing. The protocol layer is substrate-agnostic
|
||||||
|
//! by construction — socket/platform I/O is confined to the
|
||||||
|
//! feature-gated `local` backend (the default crate is wasm-clean).
|
||||||
|
//!
|
||||||
|
//! - Wire format: `docs/architecture/wire.md` (+ BAST at `bast.md`)
|
||||||
|
//! - Open-op params: ADR-001; codec: ADR-003; ALPN: ADR-002
|
||||||
|
//! - Producer shapes: ADR-004; consumer session: ADR-005; ACL: ADR-006
|
||||||
|
|
||||||
|
pub mod consumer;
|
||||||
|
pub mod error;
|
||||||
|
pub mod params;
|
||||||
|
pub mod producer;
|
||||||
|
pub mod wire;
|
||||||
|
|
||||||
|
pub use error::TunnelError;
|
||||||
|
pub use params::{establishment_reason, ChannelOpenError, TUNNEL_ALPN, TUNNEL_OPEN_SCOPE};
|
||||||
|
pub use wire::MAX_DATAGRAM_LEN;
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
//! Open-op params: `TunnelParams {resource, substrate}` — the
|
||||||
|
//! wire-stable carrier of "what to open" (ADR-001), plus the open-op
|
||||||
|
//! `OperationSpec` builder, the scope/ALPN/op-id constants, and the
|
||||||
|
//! typed establishment-reason helper (ADR-049 §4 surface).
|
||||||
|
//!
|
||||||
|
//! Skeleton module — the schema-validation tests land with
|
||||||
|
//! `tunnels/params`; the spec builder shape is already final here.
|
||||||
|
|
||||||
|
pub use alkcall::channels::client::ChannelOpenError;
|
||||||
|
|
||||||
|
/// The `channels/tunnel/sub` operation id (the open op).
|
||||||
|
pub const OP_TUNNEL_OPEN: &str = "channels/tunnel/sub";
|
||||||
|
|
||||||
|
/// The data-plane ALPN the tunnel channel carries (ADR-002: single
|
||||||
|
/// `alk/tunnel` ALPN; the substrate discriminator rides params).
|
||||||
|
pub const TUNNEL_ALPN: &str = "alk/tunnel";
|
||||||
|
|
||||||
|
/// The scope gating tunnel opens (ADR-006). Stable once published.
|
||||||
|
pub const TUNNEL_OPEN_SCOPE: &str = "tunnel:open";
|
||||||
|
|
||||||
|
/// The establishment-failure reason code of a
|
||||||
|
/// `channel:open_failed` error (`details.reason`): `dial_failed`,
|
||||||
|
/// `unknown_resource`, `resource_shortage`, `handler_error`,
|
||||||
|
/// `timeout` (alkcall ADR-049 §3). `None` for any other failure
|
||||||
|
/// shape (`FORBIDDEN`, `channel:too_many_channels`, …).
|
||||||
|
pub fn establishment_reason(err: &ChannelOpenError) -> Option<&str> {
|
||||||
|
err.establishment_reason()
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
//! The producer half: the `channels/tunnel/sub` open op — spec
|
||||||
|
//! builder, establisher shapes (dial + listen), the pump handler, and
|
||||||
|
//! registration (`register_tunnel_openable`) per `producer.md` /
|
||||||
|
//! ADR-004.
|
||||||
|
//!
|
||||||
|
//! Skeleton module — filled by `tunnels/producer-open-op` (establisher
|
||||||
|
//! + pump handler + registration) and `tunnels/producer-listen` (the
|
||||||
|
//! listen establisher variant).
|
||||||
|
|
||||||
|
pub use crate::params::{establishment_reason, OP_TUNNEL_OPEN, TUNNEL_ALPN, TUNNEL_OPEN_SCOPE};
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
//! The data-plane codec (ADR-003): raw pass-through for stream
|
||||||
|
//! substrates (`tcp`, `unix`), mandatory `[len: u16 BE]` per-datagram
|
||||||
|
//! framing for `udp`. Normative WHAT in `wire.md`; the binary framing
|
||||||
|
//! carries its BAST contract at `docs/architecture/bast.md`.
|
||||||
|
//!
|
||||||
|
//! Skeleton module — `frame_datagram`, `DatagramReader`, and
|
||||||
|
//! `DatagramCodecError` land with `tunnels/wire-codec`.
|
||||||
|
|
||||||
|
/// The u16 length-field bound: datagrams larger than this are
|
||||||
|
/// rejected at frame time (ADR-003 — never a wire overflow).
|
||||||
|
pub const MAX_DATAGRAM_LEN: usize = 65535;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
id: tunnels/crate-init
|
id: tunnels/crate-init
|
||||||
name: Initialize the alktunnels module skeleton (params, wire, producer, consumer, error)
|
name: Initialize the alktunnels module skeleton (params, wire, producer, consumer, error)
|
||||||
status: pending
|
status: completed
|
||||||
depends_on: [architecture/oq-promotion-sync]
|
depends_on: [architecture/oq-promotion-sync]
|
||||||
scope: narrow
|
scope: narrow
|
||||||
risk: low
|
risk: low
|
||||||
@@ -67,14 +67,14 @@ pub mod consumer;
|
|||||||
|
|
||||||
## Acceptance Criteria
|
## Acceptance Criteria
|
||||||
|
|
||||||
- [ ] `src/lib.rs` declares `error`, `params`, `wire`, `producer`,
|
- [x] `src/lib.rs` declares `error`, `params`, `wire`, `producer`,
|
||||||
`consumer` with doc comments; public API re-exports listed (empty
|
`consumer` with doc comments; public API re-exports listed (empty
|
||||||
bodies fine)
|
bodies fine)
|
||||||
- [ ] Every skeleton module compiles (`cargo check` clean)
|
- [x] Every skeleton module compiles (`cargo check` clean)
|
||||||
- [ ] `cargo clippy --all-targets -- -D warnings` clean
|
- [x] `cargo clippy --all-targets -- -D warnings` clean
|
||||||
- [ ] `cargo fmt --check` clean
|
- [x] `cargo fmt --check` clean
|
||||||
- [ ] `cargo check --target wasm32-unknown-unknown` passes
|
- [x] `cargo check --target wasm32-unknown-unknown` passes
|
||||||
- [ ] No comments in code beyond doc comments (convention 1)
|
- [x] No comments in code beyond doc comments (convention 1)
|
||||||
|
|
||||||
## References
|
## References
|
||||||
|
|
||||||
@@ -84,8 +84,29 @@ pub mod consumer;
|
|||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
> Agent fills during implementation.
|
- All five skeleton modules created per the task's shapes, with module
|
||||||
|
docs pointing at the spec docs + ADRs and `tunnels/*` tasks that fill
|
||||||
|
them in.
|
||||||
|
- Constants placed early (`OP_TUNNEL_OPEN`, `TUNNEL_ALPN`,
|
||||||
|
`TUNNEL_OPEN_SCOPE` in params.rs — they are part of the wire surface,
|
||||||
|
not producer-only, so they live in the shared module per the module
|
||||||
|
map's "params.rs … + open-op input schema").
|
||||||
|
- `establishment_reason` is a thin delegation to
|
||||||
|
`ChannelOpenError::establishment_reason` (alkcall 0.7.0 has the
|
||||||
|
method upstream); the crate-level helper keeps the POC's free-fn
|
||||||
|
shape for consumers and re-exports the typed error.
|
||||||
|
- `MAX_DATAGRAM_LEN` (65535) placed in wire.rs — the one codec constant
|
||||||
|
ADR-003 pins regardless of the codec functions landing later.
|
||||||
|
- **`async-trait` dropped** per the task's IF: the skeleton confirms no
|
||||||
|
trait is needed (ADR-004 — halves functions, not traits);
|
||||||
|
`cargo check` passes without it.
|
||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
|
|
||||||
> Agent fills this on completion.
|
Module skeleton landed (error/params/wire/producer/consumer + lib.rs
|
||||||
|
docs + re-exports); Cargo.toml unchanged except `async-trait` dropped
|
||||||
|
(ADR-004 confirmation). Verified: `cargo check`, `cargo clippy
|
||||||
|
--all-targets -- -D warnings`, `cargo fmt --check`, `cargo test`,
|
||||||
|
`cargo check --target wasm32-unknown-unknown`,
|
||||||
|
`cargo clippy --target wasm32-unknown-unknown -- -D warnings` — all
|
||||||
|
clean.
|
||||||
Reference in New Issue
Block a user