Skip to main content

Crate zyris

Crate zyris 

Source
Expand description

The Zyris protocol stack behind one name.

A Zyris node dials a server over one websocket, announces typed capabilities — named, versioned sets of tools with JSON-Schema’d arguments — and, on the same connection, consumes the capabilities the server announces back. This crate is the whole stack behind one dependency:

zyris = { version = "0.2", features = ["full", "tls-ring"] }
use zyris::{Node, NodeKind};

let node = Node::builder().name("my node").kind(NodeKind::Service).build()?;

// `connect` keeps the link up across drops; `Node::dial` is the single attempt underneath it.
let link = node.connect("wss://attacca.cc/api/zyris/v1/ws", "znt_the_node_token").await?;
link.wait_closed().await?;

§Dialling needs a TLS provider, and it is yours to name

wss:// is TLS, rustls does TLS, and rustls has no cipher suite of its own: it reads its crate features and, when they name no provider, it panics on the first connection. That panic is deferred all the way to runtime — there is no compile_error! for it — so a build with none is green, starts, announces, and dies the moment it dials.

So neither provider is on by default and this crate answers the question itself. Turn on exactly one:

FeatureProviderWhat it costs to build
tls-ringringa working cc
tls-aws-lcaws-lc-rsa working cc, and cmake off its nine named targets

Both compile C, which is why neither is default: cargo add zyris stays buildable on a machine with no toolchain, and everything short of reaching the network works there — declaring capabilities, serving them over another transport, the wire types. A build that skipped this step and dials anyway is refused by ConnectError::NoTlsProvider, before a socket is opened, naming both features. An application that installs its own provider with rustls::crypto::CryptoProvider::install_default is believed and needs neither.

enroll names tls-ring for you, because there is no such thing as enrolling without TLS: it is an HTTPS device-grant flow, and reqwest panics while building its client rather than on a request when no provider is installed. Adding tls-aws-lc alongside overrides the choice. p2p reaches a provider too, through iroh — that one is a property of wanting QUIC rather than something this crate decided.

That is the half a node does on every start. The other half — enrolling once, keeping the account credential, and minting a node token from it — is spelled out end to end on zyris::enroll, behind the enroll feature (so it is not a link here: under default features that item does not exist). Capability declarations live in zyris::caps, behind caps; what a node implements is the node’s own decision, which is why nothing published here makes it.

Implementations of those declarations are not here on purpose: what a node offers is the node’s decision. Reference ones are separate crates, added beside this one as you want them — zyris-fs, zyris-terminal, zyris-transfer, zyris-screen. zyris-input is the exception and stays git-only: it pins a fork of enigo, and crates.io refuses a manifest naming a git source. See https://github.com/attacca-cc/zyris-protocol.

§What is where

The runtime — connection state machine, transports, capability announce and accept, the dial/reconnect loop, device-grant enrollment, the account layer — is re-exported at this crate’s root, so Node, Connection, Result and everything beside them are named directly. The layers above the runtime each get a module, and each is behind a feature:

ModuleFeatureWhat it is
capscapsThe standard capability catalogue. Declarations only.
p2pp2pTransport that carries Zyris directly between two nodes.

Each is also a crate of its own (zyris-caps, zyris-attacca, …). Depending on one directly and on this one at the same time is not a mistake and does not link anything twice: the module here is that crate.

§Why the runtime lives in zyris-core

Every crate above the runtime depends on the runtime, so the runtime cannot depend on any of them — Cargo has no cycles. The runtime therefore ships as zyris-core and this crate re-exports it whole. Nothing about that is visible in a path: zyris::Node and zyris_core::Node are one type, and a capability written against either serves the other.

Re-exports§

pub use zyris_core;
pub use zyris_caps as caps;caps
pub use zyris_p2p as p2p;p2p

Modules§

accountenroll
The account credential: what a device grant issues, and what the caller stores.
enroll
Self-registration over the OAuth 2.0 Device Authorization Grant (RFC 8628).
prelude
proto
schemars
Schemars
serde
Serde
testing
transport

Structs§

AcceptOptions
Account
A live account credential: the thing that rotates, and the thing node tokens are minted against.
AccountBuilder
AccountCredential
An account’s long-lived identity: the refresh token it re-presents forever, and the access token it presents at each dial.
AttachmentRef
AttachmentTrailer
What an attachment’s s_end carries. §4.2 allows a trailer on any stream and names sha256 as the end-to-end integrity check; for an attachment it is always present, because the receiver has no other way to tell a truncated blob from a short one.
Capabilities
What this node offers, changeable while it is connected.
CapabilityDescriptor
CapabilityHandle
Chunk
Code
What a person has to be shown in order to approve this node.
Connection
ConnectionInfo
EnrollRequest
What a node asks to be enrolled as. The scopes are granted with the credential and never widen afterwards, so this is the one moment they can be chosen.
Enrollment
One enrollment attempt in progress: the code to show, and the poll that resolves it.
IncomingCall
Linkclient
A connection this crate keeps up.
Node
NodeBuilder
NodeSpec
What a node is asked to be registered as. scopes is a request, not a grant: the server clamps it to what this account credential was given.
NodeToken
A minted node token and the identity it carries. znt_ tokens do not expire and are never rotated, so nothing here has to be handed back to the caller’s storage on a schedule — but it is the only copy, and this crate does not keep one.
Payload
RawIncomingStream
RotateError
The caller’s own words for why it could not store a rotated credential.
Streaming
ToolDescriptor
WireError

Enums§

Blob
CallLimit
How long one call of a tool may take to answer.
CloseReason
ConnectError
Why a dial did not produce a connection, in the four shades a dialler acts on differently.
Datum
EnrollError
Why an enrollment did not produce a credential.
ErrorCode
NodeKind
Outgoing
Progress
Where one poll left the grant.
RegisterError
Why an account credential could not mint a node token.
Serialization
Transfer
TransportError

Constants§

DEFAULT_SERVER_URL
The deployment a node reaches with no configuration at all.
INLINE_BLOB_MAX
How many bytes a Blob::Inline may carry before it should be an attachment instead.
MAX_HYDRATE_BYTES
How much a generated client will collect into memory to make an attachment look inline. Sized for the datums a tool call plausibly returns — a screenshot, a document — rather than for bulk transfer, which has file_io.read_stream and its chunked stream.

Traits§

CapabilityClient
ServeCapability

Functions§

decode_call
encode_response
encode_streaming
enroll
Begin enrolling this node. The returned value carries the code a person has to approve.
machine_name
This machine’s short name, or None when it has nothing usable to say.
unknown_tool

Type Aliases§

Error
ItemStream
RawItemStream
Result

Attribute Macros§

async_trait
capability