Response

The server sends exactly one response: the byte 0 and the identity as JSON, after which the scope stays open, or the byte 1 and an error, after which the finish follows.

The server sends exactly one response on the scope. After the identity the scope stays open, and the response finish ends it; after an error the response finish follows at once. No frame bearing the scope follows the finish.

[0][accepting JSON …]    once, the identity, and the scope stays open
[1][error JSON …]        once, when the identity is held, and the finish follows
  • The sequence. Exactly one response precedes the response finish. The byte 0 is the identity: the scope stays open, and the finish follows the acceptor’s stop or the acceptor’s connection ending. The byte 1 is an error: the finish follows it, and no connection is announced. A response finish that no response precedes states that the request was not served, as Endpoints provides.
  • The identity. A payload whose first byte is 0 carries, after that byte as JSON, an object with the member identity, a string: the identity of the connection the scope was opened on, as the authorization established it. A connector names the acceptor by exactly this string.
  • The error. A payload whose first byte is 1 carries, after that byte, exactly one JSON value in the form defined on the volumes::list response page. The server sends {"kind":"held"} when an accept scope is open under the identity already.
  • Malformed. A payload with no byte, a payload whose first byte is neither 0 nor 1, and a payload whose bytes after the first do not parse as the stated JSON are malformed.

The response is defined by diverge-sdk-rs/src/provider/endpoints/daemons/accept/server/response/frame.rs:

//! What a server's response frame carries for an accept.

use std::fmt;

use super::Accepting;
use crate::shared::error::Error;
use crate::wire::decode::Decode;
use crate::wire::encode::{Encode, Writer};

/// An accept's answer: the daemon's identity, and then nothing for as
/// long as the scope lives — or a failure.
///
/// A payload leads with one byte saying which — `0` for
/// [`Accepting`](Self::Accepting), `1` for [`Error`](Self::Error) —
/// and the rest is that variant's own JSON.
///
/// | the scope | means |
/// |-----------|-------|
/// | an identity, then nothing, and stays open | the daemon accepts; every connection arrives as a channel |
/// | an error, then a finish | it does not: the identity accepts here already |
/// | a finish, with no error | the accept is over — the stop, or the connection |
#[derive(Debug, Clone, PartialEq)]
pub enum Frame {
    /// The daemon accepts, under this identity. Tag `0`.
    Accepting(Accepting),
    /// A failure. Tag `1`.
    ///
    /// The one variant that ends the scope rather than adding to it:
    /// `{"kind":"held"}` for an identity that accepts here already.
    /// See [`shared::error::Error`](crate::shared::error::Error) for
    /// why it says so little.
    Error(Error),
}

/// Tag for [`Frame::Accepting`].
const ACCEPTING: u8 = 0;

/// Tag for [`Frame::Error`].
const ERROR: u8 = 1;

impl Encode for Frame {
    /// The ordinary JSON failure.
    type Error = serde_json::Error;

    // Spelled out rather than `Self::Error`: this enum has a variant
    // called `Error`, so the associated type is ambiguous by that name.
    fn encode(&self, out: &mut Writer<'_>) -> Result<(), serde_json::Error> {
        match self {
            Frame::Accepting(accepting) => {
                out.extend_from_slice(&[ACCEPTING]);
                serde_json::to_writer(out, accepting)
            }
            Frame::Error(error) => {
                out.extend_from_slice(&[ERROR]);
                error.encode(out)
            }
        }
    }
}

impl Decode<'_> for Frame {
    /// Three ways to fail, and each names which variant failed.
    type Error = FrameError;

    // Spelled out for the same reason as `encode` above.
    fn decode(bytes: &[u8]) -> Result<Self, FrameError> {
        let (tag, rest) = bytes.split_first().ok_or(FrameError::Empty)?;
        match *tag {
            ACCEPTING => serde_json::from_slice(rest).map(Frame::Accepting).map_err(FrameError::Accepting),
            ERROR => Error::decode(rest).map(Frame::Error).map_err(FrameError::Error),
            tag => Err(FrameError::UnknownTag(tag)),
        }
    }
}

/// An accept response frame that could not be read.
#[derive(Debug)]
pub enum FrameError {
    /// No bytes at all, so not even a tag.
    Empty,
    /// A tag that is neither of this frame's two.
    UnknownTag(u8),
    /// The identity did not parse.
    Accepting(serde_json::Error),
    /// The error did not parse.
    Error(serde_json::Error),
}

impl fmt::Display for FrameError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            FrameError::Empty => f.write_str("daemons accept response frame is empty"),
            FrameError::UnknownTag(tag) => write!(f, "unknown daemons accept response frame tag {tag}"),
            FrameError::Accepting(error) => write!(f, "daemons accept identity did not parse: {error}"),
            FrameError::Error(error) => write!(f, "daemons accept error did not parse: {error}"),
        }
    }
}

impl std::error::Error for FrameError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self {
            FrameError::Accepting(error) | FrameError::Error(error) => Some(error),
            FrameError::Empty | FrameError::UnknownTag(_) => None,
        }
    }
}

and by diverge-sdk-rs/src/provider/endpoints/daemons/accept/server/response/accepting.rs:

//! The accepting daemon, as the provider knows it.

use serde::{Deserialize, Serialize};

/// What the provider answers an accept with: the identity the
/// daemon's connection is authorized under, which is what a connector
/// names it by, and what the daemon names this provider by when it
/// tells a connector where a container of its runs. The daemon does
/// not choose it and may not know it until here: an outgoing
/// connection presented a credential the provider mapped to it, an
/// incoming one was dialled by the provider under a name of the
/// provider's.
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Accepting {
    /// The identity.
    pub identity: String,
}