YUME implementation status
This page is the public support boundary for the live source tree. It uses three terms deliberately:
- Implemented means code exists in this repository.
- Tested means a named executable or integration path exercises it.
- Qualified means the exact candidate passed the complete gate for the named platform and environment.
YUME 0.3.0-dev1 composes native YTP/1 as yume and yumed, using schema-1
configuration. The C ABI is an experimental interface. Release qualification
is tracked by surface below: the native programs, SDK, installed packages and
GUI each need evidence for their own environment.
Current 0.3 foundation
The experimental ABI implements explicit client credential-file validation
through yume_config_validate_client_credentials, without starting an
endpoint. It returns the private-key-derived local composite fingerprint
after native credential and key-pair checks. Its output is distinct from an
authenticated peer identity and server admission. See ABI
for caller confinement, file lifetime and buffer requirements.
Foundation components
Implemented and covered by focused tests:
- a dependency-pure C++20 engine foundation with move-only bounded buffers, cancellation, executor affinity, byte-channel, secure-channel, carrier, stream-handler, route-provider, exact provider descriptors, and an instance-local freezing builder;
- a role-neutral, one-session bootstrap coordinator that composes the frozen client provider chain or a server front door’s typed ready-carrier promotion, validates TLS 1.3 suite provenance and exact carrier/affinity continuity, waits for cancellation settlement, cleans every rejected layer, and reports success only after the YTP session becomes active in focused in-memory tests;
- a bounded
h2-duplexcarrier provider overSecureChannel, with genuine client priming plus extended-CONNECT acceptance, a typed live-state server-promotion seam, carrier-private record framing, move-owned outer credit, and flow-controlled send completion. Focused fake-channel tests and the H2 carrier regression (yume_h2_carrier_test) pass, and they do not establish a complete YTP session runtime; - 31-bit YTP stream identifiers with stream zero reserved for control, odd client ownership, even server ownership, and exhaustion checks;
- a dependency-pure YTP/1 protocol kernel with bounded canonical frame, OPEN, destination, capability, credit, AUTH-TLV, mandatory-security-parameter, and key-schedule-input codecs;
- entirely new
yume/ytp/1/...domains plus checked-in canonical encoding vectors; - an OpenSSL 3.5 session-security provider candidate with exact Ed25519 plus ML-DSA-87 authentication, X25519 plus ML-KEM-1024 establishment, per-identity access PSKs, exporter/transcript/capability binding, one-use AES-256-GCM record keys, and crossed directional rekey tests. It is wired to the source-level native endpoint composition, with production qualification still open;
- a Boost.Asio client TCP ByteChannel provider with
bounded DNS/connect work, socket-protection-before-connect, bounded ordered
operation queues, per-operation and provider cancellation, real TCP
half-close, and explicit executor affinity. An accepted-channel owner shares
the same channel implementation for connected server sockets. Listening
belongs to the separate native FrontDoor. NativeEndpoint composes these
providers for the development CLI and schema-1 ABI backend. Both use the
caller-owned single-runner
AsioExecutionContextand reserved control dispatch. Initiation occurs on its context, while cancel/close can cross threads; the runtime must close owners and drain completions before stopping execution. Provider regressions exercise sustained allocation failure during control dispatch, read/write initiation and queue reuse, active read/write cleanup, owner destruction and resolver delivery under allocation failure. The native runtime contains Asio delivery exceptions and resumes cleanup. Endpoint integration tests are described below; - a
SystemResolverthat runs system name lookup in a killable helper process, one thread per lookup, with bounded outstanding and abandoned work. Cancellation settles at once, and closing the resolver kills and reaps the helper. The helper inherits only its standard streams and socketpair and drops every capability. Resolver, provider and endpoint tests use a helper whose test name never resolves: cancellation, helper replacement after abandoned lookups and endpoint close all settle, and final drain finishes within two seconds. The development programs are their own helper. The ABI names an installedyume-resolverthroughresolver_program, and without one a client that dials a name fails to start; - an OpenSSL 3.5 TLS 1.3 secure channel which
wraps arbitrary engine byte channels through memory BIOs, enforces exact
TLS 1.3 plus ALPN
h2, verifies client-side hostname/trust, exposes bounded outer certificate evidence and exporter binding, and keeps its provider provenance immutable. Its client applies the shared browser profile through patched OpenSSL, while refusing negotiated TLS 1.2 or HTTP/1.1 before publication. The separate server-cover entry accepts ordinary TLS 1.2/1.3 H2 cover, refuses HTTP/1.1-only ALPN offers and sends a fixed HTTP/1.0 403 response to clients without ALPN.NativeEndpointcomposes both paths. Full-session stealth qualification remains open. - exporter-bound H2 admission helpers with a separate YTP domain, exact 32-byte key, strict name/path encoding, and client-carrier proof generation. Shared replay reservations use monotonic expiry and refuse saturation or allocation failure. The native FrontDoor composes these checks with cover and connection-lifetime promotion policy;
- strict immutable numeric config schema 1 with closed objects, duplicate-key rejection, exact provider values, file-only credential references, bounded services/adapters/resources, canonical direct-adapter destination networks, and RFC 6901 error locations;
- the experimental role-neutral C ABI v1 candidate header, symbol allowlist, typed metadata and diagnostics, and exception-contained handle scaffolding;
- an explicitly enabled unversioned
libyume.sobuild-tree library with build-tree C and C++ consumers that verify metadata, schema-1 configuration, handle lifecycle, registration ordering, and a real transport start reaching the runtime rather than a stub, plus an integration probe that provisions a real server and client and moves bytes both directions over an authenticated named service stream. A client’s socket protector sees its TCP dial to the server, or to its SOCKS5 proxy, and a refusal fails the dial. A server refuses a protector. The candidate has no frozen ABI package.YUME_INSTALL_EXPERIMENTAL_SDK=ONenables development installation of the unversioned library, C header, CMake package and pkg-config metadata. The clean-prefix consumer gate runs when installation and tests are enabled. With the native daemon built, both CMake and pkg-config consumers exchange authenticated named streams/packets and routed TCP/UDP using the original probes and staged programs. Selected consumer language, C++ runtime and sanitizer options are preserved across both discovery paths.tests/abi/install_consumer/consumer.cis not idle: the shared-ABI build compiles it asyume_c_abi_consumer_c, which checks that the public header still parses as strict C11 rather than C++; - one compatibility manifest reporting product, YTP, config, ABI, logical suite components, concrete providers, cryptographic backend, and evidence-profile versions without treating an unwired component as active;
- deterministic validation of declared source dependencies and regeneration of a source-dependency SPDX SBOM. This inventory is not proof of source ancestry.
Ingress front door
The native H2WebFrontDoor implements a TCP listener over the
accepted-channel owner, ordinary TLS 1.2/1.3 H2 cover traffic and strict
TLS 1.3/H2 admission promotion. Its operator-supplied immutable
static site uses confined FileRoot reads and has no fallback content.
Invalid, missing, replayed or saturated admission stays in cover handling.
GET and HEAD serve static routes. Other methods receive the fixed 405.
Actual received SNI and locally derived TLS exporter bytes bind verification;
a shared bounded replay cache and permanent per-connection state allow at most
one promotion during the TLS connection’s lifetime.
Promotion transfers the same TLS and H2 objects after output and timer drain. The carrier retains parser and flow-credit state, queued output, cover handling, provider provenance, executor affinity and accepted TCP ownership independently of the listener. The caller supplies and drains the execution context, contains runner exceptions and resumes cleanup. The front door binds H2 ordinary dispatch and reserved control delivery to that context. H2 close, cancellation and credit return use the same allocation-free mailbox as TCP; TLS/H2 failure settlement preserves callbacks when diagnostics cannot allocate. Ingress resolves no names. The source-level native endpoint now connects this ingress to session bootstrap, and the experimental schema-1 ABI backend composes that endpoint.
yume_h2_web_front_door_test exercises real loopback TLS/H2 ingress, configured
cover responses, invalid-then-valid admission on one connection, exporter
mismatch, replay expiry, cache and promotion-capacity saturation, bidirectional
carrier records larger than the initial H2 window, cancellation, handshake
deadline cleanup and listener-independent carrier lifetime. A real occupied-port
test preserves the original listener. Linux GNU/Clang tests inject bind errors
at the syscall boundary to verify classification and retry without changing
host privileges or resource limits. The cover-site,
TLS and H2 tests cover their separate parsing and ownership boundaries. These
focused checks do not establish AUTH, a complete YTP session or a YTP ABI path.
Automated evidence
The lasting automated evidence includes warning-as-error builds, strict C and C++ ABI consumers, exact built/header/map/candidate-symbol agreement, schema examples and negative parser cases, real-key hybrid handshake/record/rekey tests, malformed canonical-codec cases, fake-channel TLS/H2 provider tests, real loopback TCP and connected-UDP route tests, the H2 carrier regression, and the end-to-end ABI named-stream probe. Exact candidate run results belong to CI or private qualification artifacts rather than this current-behavior document. Passing focused tests does not qualify the replacement end to end.
Native endpoint
runtime::NativeEndpoint loads protected schema-1 credentials, builds role-aware
provider graphs, wraps application handlers with immutable per-identity service
policy, and owns bounded bootstrap and session slots. Client startup bounds
dial/TLS/carrier/AUTH together; server session creation/AUTH is bounded from
validated carrier promotion, leaving idle accept waiting outside that budget.
FrontDoor separately bounds pre-promotion connections and work. An optional
endpoint-owned accept loop keeps a sized number of starts pending on every
listener and retries refused or immediately failed starts after a delay. When a
listener stops, or a retry cannot be scheduled for a listener with nothing
pending, it closes the endpoint and reports once. The standalone server uses
a reserved control task to carry a served endpoint’s terminal failure to its
first context without allocating, retaining its state through the callback.
Descriptor or memory
exhaustion in the native FrontDoor pauses accepting for one second before
retrying. Other accept failures, or failure to schedule that retry, close the
listener. Listener publication follows credential, mapped-limit and
static-cover validation. Static directory snapshots include nested assets and
require the browser profile’s priming paths. loopback_http_fetch.* fetches one
GET or HEAD from a loopback web server within fixed header, body and time
bounds, with cancellation that settles once, and probes such a server at
startup. It is the first part of a reverse-proxy cover. The FrontDoor does not
use it yet, so cover.reverse_proxy still fails start. Duplicate terminal cleanup does not
queue work after final executor drain. Explicit destination handlers may supply
one endpoint-owned route provider, subject to exact suite validation and their
application authorization policy. The native route provider shares the ingress
execution context and reserved cancellation ownership. It requires explicit
numeric-address authorization before opening any socket, including every
selected DNS candidate and IPv4-mapped IPv6. Policy errors and reentrant
cancellation settle the OPEN without connecting.
The provider also caps each authenticated route identity at half of its
pending and active limits, rounded up, across sessions and TCP/UDP services;
failed, canceled and closed opens release those reservations. A circuit exit
counts the authenticated previous hop, not the hidden client.
Session teardown notifies the endpoint through reserved control dispatch.
The endpoint frees the session slot before its optional session_ended
callback runs on the endpoint context. The native client uses this notification
to start reconnecting without polling. Failed attempts, and sessions that end
sooner than the longest backoff after authenticating, retain bounded
exponential backoff. Pending starts report failure through their own completion.
NativeClientRuntime::status() gives embedding applications a thread-safe
snapshot: connecting, connected, waiting or closed, the last failure, the
verified server fingerprint, attempt counts and traffic totals across sessions.
An optional callback reports each state change on the runtime context.
SessionEngine::traffic() supplies the per-session payload and record byte
counts. The endpoint test checks both across a reconnect.
Control socket and reload
With control.socket or yume --control-socket, both programs serve
control protocol 1 on an owner-only UNIX socket:
this snapshot with the fixed posture and tuning limits, circuits and route
proposals, route acceptance, the last 256 lines the program printed and, for
yume, a stop request. yume_native_control_socket_test covers each request,
its refusals and bounds, and the native runtime test stops a running client
over the socket.
A server endpoint reloads its credential stores on request, and yumed does
so on SIGHUP. Reload replaces the security factory that every later session
takes its credentials from, including sessions on accepts armed before the
reload, and swaps the
authorization policy that every service wrapper consults, so established
sessions apply changed grants to their next OPEN. It ends sessions of removed
identities and those beyond a lowered max_sessions, and refuses a store that
fails validation or a changed admission key. The endpoint test covers grant
changes, refusal of a malformed store, revocation of a live session and a
client added while an accept was armed.
Clusters and circuits
Servers of one operator form a cluster (cluster 1).
A server with a cluster section verifies the operator’s signed list and its
peer store, keeps one outbound link to every peer with the client’s backoff,
and admits peers’ links, granting them only yume.circuit. An expired list
closes the links and ends the peers’ sessions. A reload keeps every link whose
inputs did not change and replaces or closes the others, and the server saves
the highest serial it has loaded so that an older list is refused after a
restart too. yumed --status reports the list and each link over the control
socket. yume_cluster_list_test and the credential test cover the list, store
and saved-serial refusals, and yume_native_cluster_test runs three daemons
from yume-setup’s cluster commands: links in both directions, recovery after
a stop, a refused wrong PSK, a reload that restores a link, a newer list that
keeps every link, a removed server and a restart refused for an older list.
The links carry circuit 1. Its codec (circuit/)
and its handshake and layer constructions (providers/circuit_crypto.*) are
checked by yume_circuit1_codec_test and yume_circuit_crypto_test against
vectors from an independent Python generator, with real-key handshakes and
their refusals, and yume_fuzz_circuit1 fuzzes the codec. Every member
serves yume.circuit, answering CREATE, extending circuits over its links,
relaying cells and, when its cluster.exit names a direct_tcp service,
carrying circuits’ streams through that service’s destination policy, within
the bounds in cluster 1. It also serves the operator-signed routes view on
yume.routes, which names servers, exits and network tags without
addresses. A client needs the yume.circuit grant, which yume-setup
add-client --circuits writes. Circuit streams’ receive windows are capped at
an eighth of the session budget on yume.circuit and on links, and
yumed --status counts circuits per link and refusals by bound. The
in-memory yume_circuit_runtime_test covers the node service and the client
builder, including an even share for a circuit’s downloads and uploads over
a slow link, queued middle-hop failure delivery while an upstream write is
held, and bounded cleanup when the previous hop does not end the failed stream,
and yume_native_circuit_test runs four daemons with a test client:
two- and three-hop circuits carrying a stream both ways, an exit policy and
a non-exit refusing streams, a client without the grant, the per-client
bound, a reload under load, a stopped middle and its return, a client that
leaves while its circuit waits at the entry, a link rekey that a frozen
middle never acknowledges, a refused reload, a changed link PSK and a
removed node, each beside a circuit that must keep running.
A client with a circuits section sends every SOCKS5 CONNECT and every
forward to a destination through circuits it builds itself: it verifies the
routes view its entry serves against the kit’s copy and a saved serial,
chooses routes by the rules in cluster 1, builds a circuit when its session
starts, keeps a spare, rotates circuits, opens streams as soon as BEGIN is
on its way and refuses UDP, packet adapters and plain HTTP. It never shortens a route
on its own: a proposal waits for yume --accept-route over the control
socket, unless circuits.min_hops approves it in advance, and yume
--status shows routes and proposals. yume_circuit_routes_test,
yume_plain_http_guard_test and the credential, config, control socket and
setup tests cover the parts. yume_circuit_pool_test runs the circuit pool
over an in-memory session with real circuit nodes: the build at session
start, rotation, idle closing, the spare-failure rule, exclusion of a failed
node and its use again once it returns, the configured length coming back
after a proposal without an answer, cancellation, closing and a new session
during a build, and circuits closing inside the pool’s own loops.
yume_circuit_record_fit_test checks that a full cell of either direction
leaves as one 16384-byte TLS write. The four-daemon test runs the real yume
through three hops, the plain HTTP refusal, a proposal accepted after the
exits stopped and a pre-approved direct route. It also stops one stream’s
reader and another’s destination: healthy streams on the same circuit and
another client’s circuit keep moving, no node ends a circuit, and both
stalled streams then deliver every byte. The C ABI refuses a
circuits section.
Egress and listeners
A server configuration may set limits.max_egress_mbps. The endpoint then
paces the payload of every stream it serves, in both directions and for every
service, through one limiter that splits the rate between busy identities by
the weight in their authorized-keys entries. Each identity’s clock runs at
its share, and the shares of busy identities sum to the rate. Weights are read
at each transfer, so a reload reaches open streams. A held transfer checks its
stream every 250 ms and ends at once on close, so pacing cannot hold teardown
or the final drain. Transfers already scheduled keep their share when another
identity starts sending, so the total can briefly exceed the rate. Unit tests
cover shares, weights, idle identities and every settlement path, and the
endpoint test measures pacing on a live stream in both directions.
Listener socket setup preserves OS permission refusal, address conflict, invalid-address and resource-exhaustion status through the runtime and embedding seams. Unknown socket failures remain generic I/O failures; an unexpected exception is not reported as memory exhaustion. The C ABI probe exercises a conflicting listener, failed-start state, retry after port release, and restart of the original endpoint before exchanging authenticated traffic.
Integration tests
Native integration tests provision actual setup credentials and exercise
loopback TLS/H2, composite AUTH, named bytes in both directions, simultaneous
directional rekeys, half-close, refused service opens with a surviving session,
idle accept survival, stalled AUTH deadlines and final handle cleanup. Lifecycle
regressions cover closure from another thread, pending-read settlement before
notification, reentrant slot reuse, callback exceptions, client reconnect
with SOCKS traffic through the replacement session, and backoff after a session
that ends right after AUTH.
Engine regressions retain closing entries through crossed FIN, abort and
settlement in both roles, reject invalid peer barriers and keep withheld
settlement within the existing stream bound.
The established endpoint rekey cases explicitly initiate rotation. The session
engine also rotates on its own. An epoch ends at the session’s epoch size of
directional payload, one protected record per 2 KiB of it, or 500 ms of
sending. Its rotation starts at half of any of these, and the epoch keeps
carrying records while REKEY_ACK is outstanding until a limit is reached. The
receiver keeps the old inbound root only until the peer’s first record of the
new epoch. The epoch size is the smaller limits.max_epoch_bytes of the two
capability manifests, 1 MiB by default and at most 64 MiB, and engine and
endpoint tests cover a pair of sides that advertise different sizes.
With limits.idle_epoch_rotation, which the fast and max presets set,
the native endpoint’s rekey timer also starts the rotation of a used epoch
once it is 250 ms old, so a request after an idle moment does not wait for
REKEY_ACK. It is off by default, because that exchange after every burst of
traffic is visible in the stealth captures.
It reserves outbound space for rekey controls and for one of its own credit or
CLOSE records. Credit, FIN, terminal CLOSE and settlement records that do not
fit wait as bounded obligations, and engine tests cover them behind held data,
pending writes, stream churn and PONG traffic. Focused engine tests cover byte,
record and send-age thresholds, idle rotation, crossed rotation, synchronous ACK delivery,
reserved queue capacity, peer overshoot refusal, deferred publication and ACK
deadline expiry. The native endpoint also tests its unanswered-ACK watchdog.
Competing-stream tests cover credit changes, stalled readers, callback reentry
and release after rekey. Receive windows batch consumed credit and grow while
the application drains them within two round trips. Connection credit also
returns below the batch threshold when the peer has less than one maximum
frame left. Receiver tests in both roles keep one stream unread while three
others consume checked data, then drain or close the held stream and verify
continued progress within the original windows. They cover queued and
application-held records, including useful consumption before the unread
stream spends the final connection grants. Engine tests
cover the return point, growth to the bound, a slow reader whose window stays,
a peer that cannot buffer past its credit and grants above the local maxima. An
endpoint test covers a client whose byte budget is smaller than the server’s.
The admitted H2 carrier’s receive window is twice the budget, from 8 MiB to
128 MiB. Carrier tests cover its bounds and a peer that may send the whole
window before any credit returns.
These cases do not establish sustained real-carrier fairness or high-RTT
behavior.
Automatic rotation remains an open security-preservation gate despite the
changed build default.
Deterministic pacing tests cover accept refusal, unschedulable retries,
re-entrant completion, stopped listeners and close. Socket tests cover loop
exclusivity, capacity recovery and a promoted carrier that never authenticates,
plus two listeners and an injected OS accept failure on Linux.
Enabling the Asio route provider also exercises
real TCP and UDP destination traffic through configured direct_tcp/direct_udp
adapters, packet boundaries, refusal by credentials, configured destinations,
request policy and resolved-address policy before socket creation, and retained
route/credit destruction after endpoint drain. Native composition requires an
explicit provider, enforces each direct adapter’s schema-1 destinations before
an optional application policy, refuses duplicate binding ownership, and
preserves the caller’s provider on failed creation. NativeEgressPolicy tests
cover public and explicit networks, never-permitted addresses, IPv4-mapped IPv6
and per-protocol rules. egress_lists.* reads egress lists (JSON lists, the
binary VPN provider database and MaxMind country databases) into disjoint
address ranges, where the most specific range decides and Deny wins a tie.
Direct adapters take them through destinations.lists and
country_database, and they only narrow what the adapter permits.
NativeEgressPolicy reads the files at start and in --validate, adapters
with identical lists share one copy, and the endpoint and its route provider
share one policy, so the request and resolved stages decide with the same
lists. The runtime test shows a list refusing a destination that the
adapter’s networks permit. yume-doctor checks each list file’s type and size
but not its contents, and SIGHUP does not reload lists.
The canonical network grammar shares test vectors with
yume-doctor. Engine dispatch supplies the selected provider to the handler; it
cannot accidentally validate one instance while the built-in handler uses
another. The public ABI backend still rejects adapter declarations, and
carries a device’s traffic through its device bridge instead.
Engine tests separately exercise acceptance and
ordered terminal acknowledgement; bootstrap allocation sweeps cover client and
server startup and selected teardown paths. These checks are not comprehensive
allocation-failure, application-adapter, sanitizer or security qualification.
Embedding ABI
Enabling the shared ABI builds every native provider. Its experimental
yume_embed backend runs NativeEndpoint on its own execution thread
behind the blocking C ABI. Schema-1 clients open, and servers accept,
authenticated named byte streams and packet channels with the composite peer identity.
Clients also open TCP/UDP destinations through a native daemon’s declared direct services. A server
holds each authorized OPEN until the application accepts it, and a client opens
only services its configuration declares. Configured services the application
did not register are refused, and declared adapters or reverse-proxy cover fail
start explicitly. Engine reads report the peer’s authenticated FIN with a
dedicated EndOfStream status. The responder’s thread-safe terminal observation
overrides retained EOF and unread adapter records after abort or session loss.
Accept transfers local ownership without waiting for execution-thread dispatch;
shutdown deadlines cover that dispatch as well as prior writes. An escaped
runner exception closes the endpoint and drains accepted work. The
native FrontDoor enables address reuse on POSIX, so a restarted server can
rebind its port. yume_abi_stream_integration exercises setup-generated
credentials, peer identity, refused opens, deadlines, half-close, stop, restart
and stream handles that outlive their endpoint. yume_native_backend_test also
pauses execution to check deadline handling, acceptance rollback, partial-read
credit lifetime and cleanup after an escaped delivery exception.
yume_native_backend_open_integration also stops device-backed startup against
a peer that accepts TCP without answering TLS, checks that the startup waiter
returns Cancelled after final drain, and verifies release of its run ownership.
It repeats authenticated client lifetimes with two runs apiece and checks that
startup, run, session and context owners expire after close, with stable
event-loop descriptor counts after warm-up on Linux.
The standalone programs compose NativeEndpoint directly. This embedding
backend has no production qualification.
A client endpoint of the ABI can carry a TUN device the application owns,
such as an Android VpnService’s. runtime/device_bridge.* turns each TCP
connection into a stream OPEN and each UDP destination into a packet OPEN
on the kit’s ordinary services, as the SOCKS5 adapter does for a local
application, so no packet service or TUN is needed on the server.
runtime/device_nat.* rewrites TCP segments so the host’s kernel
terminates each connection on the bridge’s listener, and the library
contains no TCP implementation. Such an endpoint keeps its session up with
the SessionKeeper that yume uses. yume_device_nat_test checks the
rewriting and its checksums against a full computation, and
yume_abi_device_integration sends real TCP and UDP of sockets in one
network namespace through a real yumed in another: 300 connections at
once, shared name lookups, refused destinations, a lost and replaced
session, an immediate retry, a path that stops answering, which ends the
session at YTP/1’s 30 s rotation acknowledgement deadline, a restart and a
stop. IPv6 legs need a host kernel with IPv6. The Android client, in its
own repository, runs on this bridge, and one device cycle on a Pixel 9 Pro
with Android 17 against a real yumed passed the legs the
leak-tight page lists. Android links
libc++, so the native suite was also run with clang and libc++ on the build
host. CI’s libcxx job builds the same native and module graph with libc++
and runs the shared-ABI and native tests. Retry-timer failure fixtures cover
Asio’s POSIX aligned allocation route as well as its C++ and aligned_alloc
routes, so a fault cannot silently miss timer initiation on that library.
The ABI also reports an endpoint’s status snapshot and the lines it has
said, cancels a client start from another thread, and opens a
sealed kit in memory.
yume_abi_stream_integration reads the snapshot and the feed at each step
of a real session and cancels a start against a server that never answers,
and yume_abi_kit_integration opens a kit that the yume program sealed
and checks what the library refuses instead.
The status snapshot retains successful authentications through session end,
intentional stop and stopped backend replacement. An accepted STARTING
transition begins a new counter generation at zero; a call rejected before
that transition preserves the previous one. Failed, cancelled and expired
starts report zero counters in their new generation.
Device reconnections accumulate within that generation, with failed_attempts
reset at each authentication; both counts survive stop. Sticky last_failure
and handle-wide traffic totals keep their separate lifetimes.
yume_native_backend_open_integration pauses notification delivery for
both stream and packet sessions to check that ENDED is published with
its typed reason and lifecycle line, and that intentional stop records
no failure. Its counter assertions retain authenticated sessions through
pending and delivered end notifications and stop. The public stream fixture
also checks counter generations across failed, cancelled and expired starts,
stop, stopped backend replacement and restart; the device fixture checks
counts across reconnects, stop and restart.
Native programs
The native executables yumed and yume run schema-1 configurations.
YUME_BUILD_NATIVE_APPLICATION=ON builds the complete provider graph, as does
YUME_BUILD_SHARED_ABI=ON. Providers have no individual build switches. --config
selects the file, --validate checks configuration and credentials, and
security policy has no CLI override. The client’s --connect,
--socks-address and --socks-port each replace one configuration key for a
run and pass that key’s checks. The daemon serves configured
direct_tcp/direct_udp adapters and refuses a service without one, because
only an embedding application can supply a named-service handler. The client
keeps one authenticated session and starts a replacement when the endpoint
reports closure. Failed attempts and short sessions use bounded exponential
backoff. It refuses
server-initiated OPENs and runs the configured loopback SOCKS5
listeners. A CONNECT becomes an authenticated OPEN, and after the peer accepts
it the socket and stream share the direct-route bridge. Payload sent with
CONNECT stays unread in the socket until that bridge takes ownership. Only the
no-authentication method, CONNECT and UDP ASSOCIATE are offered, and a request
without an active session is refused rather than queued. A client may set
connect_address to dial a numeric address while TLS and admission still
authenticate host. socks5_upstream.* can reach the server through a SOCKS5
proxy instead: another byte-channel provider connects to the proxy, which is
then asked to CONNECT to the server by name or address, with or without
username and password authentication, reading no byte past the proxy’s reply
and bounded by one deadline. A client configuration’s endpoint.socks5_proxy
selects it, with credentials read like the other protected files, and a managed
TUN then keeps the proxy’s route outside the tunnel. The runtime test runs a
second client through an authenticating proxy.
yume_native_runtime_test provisions a kit, runs both
processes, moves a payload through SOCKS5, checks refusal by configured
destinations and by an unreachable route, and requires clean SIGTERM exits.
It also checks early binary payload with CONNECT or greeting+CONNECT, split
request writes, exact byte delivery and responses after the client half-closes.
An early payload cannot bypass destination policy or replace the session.
The adapter cancels a CONNECT whose OPEN deadline expires and replies with
SOCKS5 0x06 (TTL expired). Late acceptance cannot revive it. The native endpoint
test holds acceptance open to check expiry, later requests on the same session,
ordinary refusal, adapter shutdown and an accepted stream outliving its OPEN
deadline.
On Linux with GCC or Clang, yume_native_runtime_dns_test also checks allowed,
denied and mixed DNS answer sets in both orders. Its test daemon wraps the OS
resolver and observes socket creation while running the production runtime.
Refused sets open no sockets, return SOCKS5 reply 0x02, and leave the session
usable. Asynchronous permission refusal uses the existing unauthorized CLOSE
code instead of reporting a handler failure.
A client forward adapter turns each connection to its loopback TCP port or
UNIX socket into an authenticated byte-stream OPEN on its service, carrying its
optional fixed destination, and joins them with the same route bridge. SOCKS5
and forwards share LocalListener, which owns the accept retry and pause
rules and the UNIX socket checks: a directory owned by the user and closed to
others’ writes, a 0600 socket file, peer credentials of the same user,
replacement of a stale file and removal on close. The accepted-channel owner
adopts UNIX stream sockets with the TCP channel implementation and capacity.
The endpoint test checks an accepted forward in both directions with its
destination and early payload, OPEN expiry, a refused service, no active
session and a UNIX listener. The client runtime test forwards through a
configured UNIX socket after a reconnect. Unit tests cover the UNIX path rules
and channel adoption.
A server module adapter binds its stream service to a ModuleConnector.
At startup and with --validate, the daemon checks the module’s socket: a
UNIX socket of its own user with no group or other access, in a directory
that only root and that user can change. Each connection also requires a
listener created by root or that user. Each authorized OPEN
without a destination becomes a connection that starts with a yume-module 1
header naming the client identity, joined to the stream by the route bridge.
A service manager owns the module’s process and socket. The Debian package
ships yume-module@.socket and yume-module@.service templates, which run
each module as a dynamic user of its own in a sandbox without a network.
Unit tests cover the socket checks, a module restart with half-close and a
stream that waits in the socket’s queue, a removed socket and allocation
failures. The endpoint test reaches the echo module through a client forward,
and the runtime test serves it under the real yumed and checks that
--validate refuses a socket open to the group. The installed units have not
run on a qualified host.
With YUME_BUILD_BASEFWX_MODULES, yume_module_relay builds the relay v2
end-to-end channel apart from transport v2: the composite-identity handshake
with ML-KEM-1024, X25519 and an optional PSK, the sealed record format and the
hybrid ratchet with its rekey records. Its tests check known answers produced
by the transport-v2 code for epoch roots, ciphertexts and whole records, so
the copy keeps every label and wire value. A known-answer test also checks
every handshake and ratchet label on the
relay channel page against an independent Python
reference. The same library holds the stores a
relay user keeps: chat history encrypted at rest, the relay secret derived
from a password with PBKDF2, and peer trust with first-use and pinned
fingerprints. Peer fingerprints are now YTP/1 identity fingerprints, the value
yume-setup prints for a key. It also holds the relay’s invite, endpoint and
directory records with their strict JSON parsers, the message policy that
decides which relay message may follow which, and the bounds on pending
invites. History records require exactly ts_ms, peer_id, peer_name,
direction and text, with no duplicate or nested fields. Timestamps fit
signed 64-bit integers, the other fields are strings, peer IDs are nonempty,
and direction is in or out.
Invalid records make the list unavailable and return no items. YUME’s guarded
plaintext buffers are wiped on release as best effort. JSON-library parsing and
serialization can retain ordinary-memory copies outside those guards.
yume_module_files adds relay file transfer:
a source pinned to one opened file that hashes and sends the same bytes, and a
receiver that writes into a private staging file and publishes it without
replacing anything, only after the declared size and SHA-256 match.
It rejects unrepresentable receive deadlines before creating state, and
cleans up failures before allocating diagnostics. The relay channel reference
owns the history layout and trust-commit durability rules.
yume_module_codecs holds the application codec core without BaseFWX: the
HTTP request and response envelope, backend dialing rules and the Monero RPC
descriptor with its request allow-list. No module uses these libraries yet.
Client kits move between devices as sealed kits,
which need only the core’s OpenSSL 3.5 and replaced the BaseFWX .yss
container library.
UDP ASSOCIATE uses the SOCKS5 adapter’s configured udp_service. A loopback
relay accepts datagrams only from the requesting client and gives each
destination its own authenticated packet OPEN, so identity grants and
direct_udp destinations apply as they do to CONNECT. Backlogs follow the
shared UDP policy of 64 datagrams and 1 MiB per budget, dropping the newest
datagram when full. Destinations close after an idle timeout, refused ones wait
a retry delay, and the association ends with its TCP connection. The route
bridge drops an empty datagram from a destination instead of closing the flow,
because a YTP packet cannot be empty, and drops one larger than the session’s
packet bound the same way. The native endpoint test runs UDP
ASSOCIATE over the production daemon composition with real UDP sockets. It
checks traffic both ways, an empty datagram from the destination, refusal by
configured destinations and by a missing identity grant, source locking, the
unsupported reply without a UDP service, relay closure, and the 64-datagram
budget while an OPEN is held. yume_native_runtime_test repeats the traffic,
refusal and closure checks between the two processes, which start from the
generated setup kit’s services and adapters.
CMake installs these development programs together with the native schema-1
yume-setup and yume-doctor programs, which make and check kits with the
same OpenSSL release and credential readers. The Debian 13 package and systemd
integration covers disabled installation, provisioning and doctor, checked
loopback TCP and module streams, permission/configuration refusals, credential
reload, stop, crash restart and client reconnection. Package checks also cover
same-version upgrades, removal and purge, and refusal to replace the patched
OpenSSL dependency with stock. Production and real-network qualification remain
separate.
An unrecoverable reconnect timer or SOCKS listener retry failure closes the client runtime and reports a typed terminal status. Both CLIs exit with failure after draining owned work. Explicit shutdown does not emit that failure, and ordinary connection failures still retry with backoff. After a runner exception, the CLI uses a reserved control task to close every runtime on its execution context, then drains accepted completions. The runner regression covers live accept/timer cancellation during sustained allocation failure and a second exception during drain.
The native Linux runtimes also compose named IP packet services through
NativePacketAdapter, IpPacketChannel and LinuxTunNetwork. They own an
ephemeral TUN, explicit addresses/routes and optional systemd-resolved per-link
DNS. An exclusive session lease drains OS callbacks before reconnect; shutdown
checks network cleanup. See the native guide
for address policy, routing exclusions and qualification limits.
The optional yume_native_resolved_test runs an actual systemd-resolved
service and a private D-Bus inside unprivileged user, mount and network
namespaces. It verifies per-link DNS servers, routing domains, default-route
policy, DNS queries through the tunnel, reconnect and shutdown cleanup. The
regular TUN test still exercises DNS-free configurations. Service deployment
and managed TUN DNS have separate lifetime and privilege boundaries.
Remaining qualification and integration
These qualification and integration tasks remain open:
- complete-session qualification of the native FrontDoor, including external comparison of ordinary and rejected-admission cover behavior;
- production qualification of
yume,yumedand the experimental schema-1 ABI backend; - extended real-carrier rekey, close-ordering and credit/backpressure qualification beyond the focused native-session regressions;
- acceptance evidence for automatic directional root rotation and competing-stream scheduling, including stalled readers, cancellation and real-carrier pressure;
- production qualification of module adapters and managed TUN;
- circuits: held-out classifier comparisons of client sessions and node links, sustained cross-host loss and latency testing, upload window growth at the exit, UDP and IP carriage, and a consent interface in the C ABI;
- complete installed-SDK qualification across the supported build/toolchain matrix;
- distribution publication of the patched OpenSSL dependency and qualification
of each exact candidate package, remaining consumer migration around native
yumeandyumed, and a qualified setup-to-first-SOCKS path over a real network; - a release-workflow run with the configured signing secret and existing release target. Local rejection tests cover trusted commit/tag verification, required signatures, manifest consistency and refusal of existing asset names, as operations describes;
- complete-session active-probe, classifier, performance, soak, fuzz and sanitizer qualification.
Across-operator transit and decentralized discovery are later design work.
Existing integration coverage
Native CTest registration includes the schema-1 setup and doctor negative
cases, a sweep of one allocation failure across key generation, init,
secret copies and the doctor that checks every released buffer for an
unwiped secret, project metadata and Linux release-archive checks.
The Clang fuzz profile instruments the YTP frame/OPEN/capability codecs, AUTH
TLVs and schema-1 parser, including their source libraries. Numeric overflow
in JSON is a typed validation failure.
With Linux namespace tests enabled, YUME_TEST_NATIVE_STRESS=ON adds a delayed
carrier workload with an unread destination, competing transfers, ordered
recovery, half-close, stable carrier sockets and RSS/descriptor growth guards.
Address-sanitized builds select the fixture’s --asan profile: a 16 MiB global
quarantine and 64 KiB per-thread quarantine, with leak detection and fatal
sanitizer errors enabled. This bounds deliberately retained freed storage
without raising the 256 MiB RSS growth guard. Other sanitizer tests keep their
existing options. This finite workload does not measure live queue ownership,
prove a memory plateau or observe automatic rekeys.
The optional desktop GUI, yume-gui (YUME_BUILD_GUI=ON, Qt 6.4 or later),
starts each kit’s yume detached, stops it with the control socket’s stop
request and shows its status, printed lines, posture and route proposals.
It imports sealed kits through yume --import-kit and accepts a shorter route
only from a review of that exact proposal. yume_gui_test,
yume_gui_ui_test, yume_gui_ui_rtl_test and yume_gui_live_test cover the
lifecycle, keyboard access, right-to-left layout and a live connect, stop,
reconnect and stop against a real daemon. Its tray icon shows the selected
kit’s state. The GUI is not packaged, runs only on Linux, starts nothing at
login and does not restart a crashed client.
See the desktop GUI. CodeQL
analyzes the native programs, libyume and the module libraries. Debian definitions
use the native config-only daemon, validate configuration before startup and
leave the service disabled after installation. Native release archives carry
the native setup and doctor programs and enforce native executable identities; packaging regression
checks do not qualify a distribution or an installed service.
The C ABI attaches the native runtime through its one backend and accepts only
schema-1 documents. yume_endpoint_start starts a client or server,
yume_endpoint_register_service, yume_endpoint_open_stream and
yume_endpoint_accept_stream carry authenticated named byte streams, and
yume_stream_read, write, shutdown_write and close move real bytes with
typed transport failures. Native packet channels support named services and
routed UDP with bounded whole-packet batches.
IpPacketChannel validates IPv4/IPv6 lengths, exact packet size, MTU and
directional address policy before forwarding through the native route bridge.
The Linux packet adapter puts it behind a managed TUN device, which owns
addresses, routes and per-link DNS.
Security boundary
The YTP/1 design requires all of the following:
- Ed25519 and ML-DSA-87 authentication;
- X25519 and ML-KEM-1024 establishment;
- a distinct per-identity random access PSK;
- the live TLS 1.3 exporter and exact roles, identities, transcript, capabilities, suite, and fixed security parameters in the key schedule;
- independent directional ratcheting, one-use AES-256-GCM keys for protected records, and a candidate-new-root authenticated rekey acknowledgement;
- bounded work and allocation before attacker-controlled parsing, KEM, stream creation, queueing, or rekey preparation;
- hard failure on a missing component, provider mismatch, role confusion, replay, malformed canonical encoding, or authentication failure.
The provider selected by the native application implements the cryptographic portions and has focused tests with real keys; dependency-pure engine tests cover the matching record and resource contracts. Native endpoint integration connects the live TLS exporter, carrier and session security. Published synthetic construction vectors check deterministic transcript, key schedule, record protection and rekey calculations against an independent generator. Independent-peer interoperability, broader qualification and an independent security review remain open. Review is planned alongside development and is not a release prerequisite. Ratchet recovery depends on fresh uncompromised contributions and erasure, as the threat model describes.
Ingress evidence boundary
The retained transport-profile capture pipeline and immutable Chrome/Node fixture are evidence inputs, not a claim of universal indistinguishability. Any release claim must name the exact profile, capture, candidate binary, environment, TLS/H2 semantic results, active-probe cover results, and held-out classifier result. ALPN, JA3/JA4, or a short successful navigation is insufficient.
Performance boundary
Throughput tuning has matched measurements of carrier buffering and event-loop scaling on loopback and emulated paths, including the preset measurements in the configuration reference. Those measurements do not establish real-path speed, latency, or fairness. A comparison must report its connection geometry: YUME multiplexes streams inside one session, while an unmultiplexed reference uses a connection per stream. A claim such as “faster” requires at least five matched runs with throughput, p50/p99 latency, CPU/byte, allocations, peak memory, and 1/32/256-stream fairness plus reported uncertainty.
Freeze gates
Before 0.3.0-rc1, the exact candidate must pass:
- clean supported-platform builds and target/include layering checks;
- YTP/1 vectors, mutation/component-stripping/replay/role/provider tests, and parser fuzzing;
- ASan, UBSan, TSan, failure injection, flood/resource-pressure, and sustained soak qualification;
- clean-prefix SDK installation and C/C++ stream and packet consumers through both CMake and pkg-config;
- clean-machine setup, permissions, doctor, cover-browser, and first-stream smoke tests;
- immutable ingress/profile evidence and reproducible performance evidence;
- synchronized source, tests, help, manual pages, package metadata, website, declared-dependency/SBOM, and documentation drift checks.
Record each gate against the exact candidate, platform and environment. Use the implemented and tested descriptions above when reporting a narrower check.