# 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: the byte 0 followed by the secrets’ first values is fed to the container before the id, and anything else is the run’s error.

Canonical: https://protocol.diverge.network/2.3.0/endpoints/containers-tools-run/server/registration/response/
Specification revision: 2.3.0

```text
[0][values JSON …]   deployed: these are the secrets' first values
[1][error JSON …]    not deployed
```

- **The sequence.** Exactly one channel response, followed by the
  channel response finish. The byte `0` lets the run go on to its
  feed and its id. The byte `1`, followed by exactly one JSON value
  in the form defined on the [volumes::list response](/2.3.0/endpoints/volumes-list/response/)
  page, is the run's error, in the client's words: the server stops
  the container and sends the error as the scope's one response. A
  channel response finish that no channel response precedes is the
  run's error too.
- **The values.** The bytes after the byte `0` are a JSON object
  whose every member is a secret's name, as the declaration carried
  it, to its value, any JSON value, in the order declared: every
  name the program declared, and no other. The server relays the
  object verbatim on exactly one
  [secrets](/2.3.0/container-proxy-endpoints/tools-begin/client/secrets/)
  channel of the begin scope, reads none of it, and sends the id only
  after the proxy has answered `Fed`.
- **Malformed.** A channel response whose first byte is neither `0`
  nor `1`, or whose bytes after `0` do not parse as the values, is
  the run's error.

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

```rust
//! What a caller answers on a registration channel.

use std::fmt;

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

/// Deployed, or not.
///
/// The whole answer to a [`Request`](super::super::request::Request),
/// 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][values JSON …]   deployed: every dependency runs, and these are the secrets' first values
/// [1][error JSON …]    not deployed, and why
/// ```
///
/// A deploy carries the first [`Values`] — every name the program
/// declared, each to the value locked or read for it — which the
/// provider feeds to the container before it sends the id, and
/// nothing else: the provider needs no id of a tool container, since
/// the caller wires them. An empty map is a program that declared no
/// secret. A refusal carries the caller's own words — a dependency
/// that did not deploy, a name the template does not declare, a key
/// with no free value — which the run's error carries on, and never
/// a value.
#[derive(Debug, Clone, PartialEq)]
pub enum Frame {
    /// Every dependency runs, and the secrets have these values. Tag
    /// `0`.
    Deployed(Values),
    /// Something did not, and this says why. Tag `1`. See
    /// [`shared::error::Error`](crate::shared::error::Error) for why
    /// it says so little.
    Error(Error),
}

/// Tag for [`Frame::Deployed`].
const DEPLOYED: u8 = 0;

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

impl Encode for Frame {
    /// The ordinary JSON failure, from either variant.
    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::Deployed(values) => {
                out.extend_from_slice(&[DEPLOYED]);
                serde_json::to_writer(out, values)
            }
            Frame::Error(error) => {
                out.extend_from_slice(&[ERROR]);
                error.encode(out)
            }
        }
    }
}

impl Decode<'_> for Frame {
    /// Four ways to fail, and two of them are JSON.
    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 {
            DEPLOYED => serde_json::from_slice(rest).map(Frame::Deployed).map_err(FrameError::Deployed),
            ERROR => Error::decode(rest).map(Frame::Error).map_err(FrameError::Error),
            tag => Err(FrameError::UnknownTag(tag)),
        }
    }
}

/// A registration answer 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 values did not parse. The message is the parser's, which
    /// quotes no value.
    Deployed(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("registration answer frame is empty"),
            FrameError::UnknownTag(tag) => write!(f, "unknown registration answer frame tag {tag}"),
            FrameError::Deployed(error) => write!(f, "registration values did not parse: {error}"),
            FrameError::Error(error) => write!(f, "registration error did not parse: {error}"),
        }
    }
}

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

and by `diverge-sdk-rs/src/shared/containers/secrets/values.rs`:

```rust
//! The secrets' values, by name.

use indexmap::IndexMap;
use serde_json::Value;

/// Secrets by name to value, any JSON: what the caller feeds a
/// container, and what the program hands back. Fed, it carries every
/// name the program declared, in the order declared — a `fixed` one
/// a value read from its key, a `rotating` one the value locked to
/// the container. Collected at an inactive, it carries every
/// `rotating` name the program declared, each with the value the
/// program leaves in it; a `fixed` name in it is ignored, and a
/// `rotating` name missing from it is the collect's error, never a
/// write-back. A value is never read by anything between the vault
/// and the program.
pub type Values = IndexMap<String, Value>;
```
