refactor!: rebrand wraith to alknet
Rename all crates, CLI commands, constants, type names, doc comments, and documentation from wraith to alknet. Includes wire-protocol changes: ALPN wraith-ssh -> alknet-ssh, reserved destination prefix wraith- -> alknet-, SSH auth username wraith -> alknet.
This commit is contained in:
@@ -7,14 +7,14 @@ last_updated: 2026-06-02
|
||||
|
||||
## What
|
||||
|
||||
Two integration layers that enable TypeScript/JavaScript consumers to use wraith as a transport:
|
||||
Two integration layers that enable TypeScript/JavaScript consumers to use alknet as a transport:
|
||||
|
||||
1. **NAPI wrapper** (`@alkdev/wraith`) — A Node.js native addon (via napi-rs) exposing `connect()` and `serve()` that return duplex streams
|
||||
2. **PubSub event target** (`@alkdev/pubsub` adapter) — An implementation of the `TypedEventTarget` interface that routes events over wraith's SSH channel
|
||||
1. **NAPI wrapper** (`@alkdev/alknet`) — A Node.js native addon (via napi-rs) exposing `connect()` and `serve()` that return duplex streams
|
||||
2. **PubSub event target** (`@alkdev/pubsub` adapter) — An implementation of the `TypedEventTarget` interface that routes events over alknet's SSH channel
|
||||
|
||||
## Why
|
||||
|
||||
The wraith Rust binary serves CLI users. But the broader ecosystem (pubsub, operations, agent spokes) is TypeScript-first. These integration layers let TypeScript code use wraith's transport without reimplementing SSH.
|
||||
The alknet Rust binary serves CLI users. But the broader ecosystem (pubsub, operations, agent spokes) is TypeScript-first. These integration layers let TypeScript code use alknet's transport without reimplementing SSH.
|
||||
|
||||
The NAPI surface is intentionally minimal — it exposes transport connections as duplex streams, not the full SSH protocol. The pubsub adapter wraps those streams with `EventEnvelope` serialization.
|
||||
|
||||
@@ -25,9 +25,9 @@ The NAPI surface is intentionally minimal — it exposes transport connections a
|
||||
The wrapper uses napi-rs (ADR-015) and exposes two functions (ADR-016):
|
||||
|
||||
```typescript
|
||||
// @alkdev/wraith (TypeScript side)
|
||||
// @alkdev/alknet (TypeScript side)
|
||||
|
||||
interface WraithConnectOptions {
|
||||
interface AlknetConnectOptions {
|
||||
// TCP/TLS mode
|
||||
server?: string; // e.g., "example.com:443"
|
||||
// iroh mode
|
||||
@@ -45,7 +45,7 @@ interface WraithConnectOptions {
|
||||
proxy?: string; // upstream SOCKS5/HTTP proxy URL
|
||||
}
|
||||
|
||||
interface WraithServeOptions {
|
||||
interface AlknetServeOptions {
|
||||
// Transport
|
||||
transport: 'tcp' | 'tls' | 'iroh';
|
||||
// Auth
|
||||
@@ -63,12 +63,12 @@ interface WraithServeOptions {
|
||||
}
|
||||
|
||||
// Returns a Duplex stream for the SSH channel
|
||||
function connect(options: WraithConnectOptions): Promise<Duplex>;
|
||||
function connect(options: AlknetConnectOptions): Promise<Duplex>;
|
||||
|
||||
// Returns a server object with close() and connection events
|
||||
function serve(options: WraithServeOptions): Promise<WraithServer>;
|
||||
function serve(options: AlknetServeOptions): Promise<AlknetServer>;
|
||||
|
||||
interface WraithServer {
|
||||
interface AlknetServer {
|
||||
close(): Promise<void>;
|
||||
onConnection(callback: (stream: Duplex, info: ConnectionInfo) => void): void;
|
||||
}
|
||||
@@ -76,18 +76,18 @@ interface WraithServer {
|
||||
|
||||
The NAPI layer is **transport-agnostic** — it doesn't know about pubsub's `EventEnvelope`. The pubsub adapter wraps the `Duplex` stream to implement `TypedEventTarget`. This separation ensures the NAPI wrapper is reusable for any stream-based protocol, not tied specifically to pubsub.
|
||||
|
||||
### NAPI `connect()` vs CLI `wraith connect`
|
||||
### NAPI `connect()` vs CLI `alknet connect`
|
||||
|
||||
The NAPI `connect()` function and the CLI `wraith connect` command are fundamentally different operations despite sharing the same name:
|
||||
The NAPI `connect()` function and the CLI `alknet connect` command are fundamentally different operations despite sharing the same name:
|
||||
|
||||
- **CLI `wraith connect`**: Starts a full SSH client session with a local SOCKS5 server and optional port forwards. It manages multiple SSH channels over a single session — the user routes traffic through it via SOCKS5 or forwarded ports.
|
||||
- **CLI `alknet connect`**: Starts a full SSH client session with a local SOCKS5 server and optional port forwards. It manages multiple SSH channels over a single session — the user routes traffic through it via SOCKS5 or forwarded ports.
|
||||
- **NAPI `connect()`**: Opens a single SSH channel and returns it as a `Duplex` stream. No SOCKS5 server, no port forwarding. The caller reads and writes bytes directly. This is designed for the pubsub/programmatic use case where a single bidirectional byte stream is needed.
|
||||
|
||||
For SOCKS5 proxy functionality, use the CLI binary (`wraith connect`). The NAPI wrapper is for programmatic consumers that need a raw stream.
|
||||
For SOCKS5 proxy functionality, use the CLI binary (`alknet connect`). The NAPI wrapper is for programmatic consumers that need a raw stream.
|
||||
|
||||
### Programmatic Configuration (ADR-011)
|
||||
|
||||
Both `connect()` and `serve()` accept options as plain objects. No file paths are mandatory — keys can be provided as `Buffer` data directly, making programmatic usage straightforward. Environment variables (`WRAITH_SERVER`, `WRAITH_IDENTITY`) provide convenience defaults.
|
||||
Both `connect()` and `serve()` accept options as plain objects. No file paths are mandatory — keys can be provided as `Buffer` data directly, making programmatic usage straightforward. Environment variables (`ALKNET_SERVER`, `ALKNET_IDENTITY`) provide convenience defaults.
|
||||
|
||||
Key material provided as `Buffer` must be in **OpenSSH key format** (the format used by `ssh-keygen`). Private keys: OpenSSH format (`-----BEGIN OPENSSH PRIVATE KEY-----`). Public keys: OpenSSH format (`ssh-ed25519 AAAA...`). PEM-encoded keys (PKCS#1, PKCS#8) are not supported.
|
||||
|
||||
@@ -96,20 +96,20 @@ Key material provided as `Buffer` must be in **OpenSSH key format** (the format
|
||||
This implements `TypedEventTarget` from `@alkdev/pubsub`:
|
||||
|
||||
```typescript
|
||||
// @alkdev/pubsub (new adapter: event-target-wraith.ts)
|
||||
// @alkdev/pubsub (new adapter: event-target-alknet.ts)
|
||||
|
||||
export interface WraithEventTargetOptions {
|
||||
stream: Duplex; // from @alkdev/wraith.connect() or serve()
|
||||
export interface AlknetEventTargetOptions {
|
||||
stream: Duplex; // from @alkdev/alknet.connect() or serve()
|
||||
}
|
||||
|
||||
export interface WraithEventTarget<TEvent extends TypedEvent>
|
||||
export interface AlknetEventTarget<TEvent extends TypedEvent>
|
||||
extends TypedEventTarget<TEvent> {
|
||||
close(): void;
|
||||
}
|
||||
|
||||
export function createWraithEventTarget<TEvent extends TypedEvent>(
|
||||
options: WraithEventTargetOptions
|
||||
): WraithEventTarget<TEvent>;
|
||||
export function createAlknetEventTarget<TEvent extends TypedEvent>(
|
||||
options: AlknetEventTargetOptions
|
||||
): AlknetEventTarget<TEvent>;
|
||||
```
|
||||
|
||||
Wire protocol (same as other pubsub adapters):
|
||||
@@ -121,20 +121,20 @@ Wire protocol (same as other pubsub adapters):
|
||||
|
||||
### On the Server Side
|
||||
|
||||
The wraith server uses a reserved `direct_tcpip` destination (`wraith-control:0`) for the pubsub control channel (ADR-018). When a client connects to this destination:
|
||||
The alknet server uses a reserved `direct_tcpip` destination (`alknet-control:0`) for the pubsub control channel (ADR-018). When a client connects to this destination:
|
||||
|
||||
1. The server's `channel_open_direct_ip` handler detects the reserved `wraith-control` target
|
||||
1. The server's `channel_open_direct_ip` handler detects the reserved `alknet-control` target
|
||||
2. Instead of opening a TCP connection, it bridges the channel to its local pubsub event bus
|
||||
3. `EventEnvelope` JSON flows bidirectionally over the SSH channel
|
||||
|
||||
Users who prefer not to use the control channel can alternatively run a pubsub hub on a specific port and use standard port forwarding: `wraith connect --forward 9736:hub:9736`. This is a deployment choice, not a separate implementation — wraith's port forwarding works normally for any TCP service.
|
||||
Users who prefer not to use the control channel can alternatively run a pubsub hub on a specific port and use standard port forwarding: `alknet connect --forward 9736:hub:9736`. This is a deployment choice, not a separate implementation — alknet's port forwarding works normally for any TCP service.
|
||||
|
||||
### Direction Agnostic
|
||||
|
||||
Because wraith supports both local and remote port forwarding, the event target works in either direction:
|
||||
Because alknet supports both local and remote port forwarding, the event target works in either direction:
|
||||
|
||||
- **Worker connects to hub**: `wraith connect --forward 9736:hub:9736` then create WebSocket event target pointing at `ws://localhost:9736`
|
||||
- **Hub connects to worker**: `wraith connect --remote-forward 9736:worker:9736` — same result, opposite initiator
|
||||
- **Worker connects to hub**: `alknet connect --forward 9736:hub:9736` then create WebSocket event target pointing at `ws://localhost:9736`
|
||||
- **Hub connects to worker**: `alknet connect --remote-forward 9736:worker:9736` — same result, opposite initiator
|
||||
|
||||
The pubsub adapter doesn't care which side initiated the SSH session. It just needs a byte stream.
|
||||
|
||||
@@ -157,4 +157,4 @@ None — all resolved.
|
||||
| [011](decisions/011-no-ssh-config-programmatic-api.md) | Programmatic-first API | No file-based config; options are structs or env vars |
|
||||
| [015](decisions/015-napi-rs-for-ffi-bridge.md) | napi-rs for FFI | Standard Node.js native addon tooling |
|
||||
| [016](decisions/016-napi-expose-connect-and-serve.md) | Both connect() and serve() | NAPI exposes client and server sides from the start |
|
||||
| [018](decisions/018-control-channel-for-pubsub.md) | Control channel for pubsub | Reserved `wraith-control` destination for event bus |
|
||||
| [018](decisions/018-control-channel-for-pubsub.md) | Control channel for pubsub | Reserved `alknet-control` destination for event bus |
|
||||
Reference in New Issue
Block a user