# Response

> The sequence of channel responses the client answers with, what ends it, what a finish with nothing before it means, and what the server does with the answer.

Canonical: https://provider.diverge.network/2.3.0/endpoints/containers-agents-run/server/authorize/response/
Specification revision: 2.3.0

```text
[0]      denied
[1]      authorized
```

- **The sequence.** Exactly one channel response of exactly one
  byte, followed by the channel response finish. The byte `1` opens
  the connect scope. The byte `0`, any other byte, and a channel
  response finish that no channel response precedes refuse it: the
  server answers the connector with the error `{"kind":"denied"}`.

The channel response is defined by `diverge-provider-sdk/src/shared/containers/authorize/response/frame.rs`:

```rust
//! What a runner answers on an authorize channel.

use std::fmt;

use crate::decode::Decode;
use crate::encode::{Encode, Writer};

/// Yes or no.
///
/// The whole answer to an
/// [`Authorize`](super::super::request::Authorize), and one frame is
/// all there is — this is not a stream, and a channel carrying one of
/// these finishes immediately after.
///
/// # The layout
///
/// ```text
/// [0]  denied
/// [1]  authorized
/// ```
///
/// One byte, nothing after it. A yes used to carry a nickname so the
/// runner could tell WHICH connector later left; nothing reports a
/// departure any more, so nothing has a use for the name.
///
/// # Why the answer says nothing else
///
/// A reason would have to mean something to the provider, and the
/// provider did not write the question. What was asked is between the
/// two ends; the only part this layer needs is whether the answer was
/// yes, because that is the part a provider acts on.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Frame {
    /// The connector may not attach.
    Denied,
    /// The connector may attach.
    Authorized,
}

/// The tag for a denial.
const DENIED: u8 = 0;

/// The tag for an authorization.
const AUTHORIZED: u8 = 1;

/// One byte, laid out by hand. Two tags are not a shape a format would
/// help with.
impl Encode for Frame {
    /// [`Infallible`](std::convert::Infallible): a known byte.
    type Error = std::convert::Infallible;

    fn encode(&self, out: &mut Writer<'_>) -> Result<(), Self::Error> {
        match self {
            Frame::Denied => out.extend_from_slice(&[DENIED]),
            Frame::Authorized => out.extend_from_slice(&[AUTHORIZED]),
        }
        Ok(())
    }
}

impl Decode<'_> for Frame {
    /// Two ways to fail, and neither is a parse.
    type Error = FrameError;

    fn decode(bytes: &[u8]) -> Result<Self, Self::Error> {
        let (tag, _) = bytes.split_first().ok_or(FrameError::Empty)?;
        match *tag {
            DENIED => Ok(Frame::Denied),
            AUTHORIZED => Ok(Frame::Authorized),
            tag => Err(FrameError::UnknownTag(tag)),
        }
    }
}

/// An authorization answer that could not be read.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FrameError {
    /// No bytes at all, so not even a tag.
    Empty,
    /// A tag that is neither yes nor no.
    ///
    /// Rejected rather than read as truthy. Anything other than the
    /// two defined values means the sender and this reader disagree
    /// about the protocol, and guessing which way a disagreement leans
    /// is a poor way to decide an authorization.
    UnknownTag(u8),
}

impl fmt::Display for FrameError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            FrameError::Empty => {
                f.write_str("authorization answer frame is empty")
            }
            FrameError::UnknownTag(tag) => {
                write!(f, "unknown authorization answer tag {tag}")
            }
        }
    }
}

impl std::error::Error for FrameError {}
```
