use ring::digest::{SHA256, digest};
use ring::signature::{ED25519, UnparsedPublicKey};
use serde::{Deserialize, Serialize};
const SCHEMA: &str = "saddle-f08-rendezvous-manifest/1";
const DOMAIN: &str = "saddle/f08/rendezvous-manifest/v1";
const USAGE: &str = "capacity.rendezvous.manifest";
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum RendezvousManifestPreflightError {
Encoding,
Signature,
Foreign,
Shape,
}
pub struct CanonicalSignedRendezvousManifestInput {
canonical: Vec<u8>,
signature: Vec<u8>,
}
pub struct VerifiedRendezvousManifestKeyApplicabilityReceipt {
public_key: [u8; 32],
key_identity: [u8; 32],
authority_identity: [u8; 32],
other_key_identities: [[u8; 32]; 8],
other_authority_identities: [[u8; 32]; 8],
domain: [u8; 32],
usage: [u8; 32],
}
pub struct StructurallyVerifiedRendezvousManifestPreflightOwner {
canonical: Vec<u8>,
signature: Vec<u8>,
subject_identity: [u8; 32],
key_identity: [u8; 32],
authority_identity: [u8; 32],
document: RendezvousManifestDocument,
}
macro_rules! redacted_debug {
($type:ty, $name:literal) => {
impl core::fmt::Debug for $type {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str(concat!($name, "(<redacted>)"))
}
}
};
}
redacted_debug!(
CanonicalSignedRendezvousManifestInput,
"CanonicalSignedRendezvousManifestInput"
);
redacted_debug!(
VerifiedRendezvousManifestKeyApplicabilityReceipt,
"VerifiedRendezvousManifestKeyApplicabilityReceipt"
);
redacted_debug!(
StructurallyVerifiedRendezvousManifestPreflightOwner,
"StructurallyVerifiedRendezvousManifestPreflightOwner"
);
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct RendezvousManifestDocument {
schema: String,
signature_domain: String,
usage: String,
algorithm: String,
key_identity: String,
authority_identity: String,
five_leaf_v2_subject_identity: String,
five_leaf_v2_observation_identity: String,
approved_lock_identity: String,
root_schema_identity: String,
composer_schema_identity: String,
common_identities: [String; 3],
owner_generation: u64,
leaves: LeavesDocument,
normalized: NormalizedDocument,
termination: TerminationDocument,
constituent_commitments: CommitmentsDocument,
}
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct LeavesDocument {
service: ServiceDocument,
runtime: RuntimeDocument,
calibration: CalibrationDocument,
admission: AdmissionDocument,
observability: ObservabilityDocument,
}
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct ServiceDocument {
leaf_identity: String,
common_identities: [String; 3],
owner_generation: u64,
route_type_closure_identity: String,
routes: Vec<ServiceRouteDocument>,
}
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct ServiceRouteDocument {
ordinal: u64,
route_id: u64,
managed_commitment_bytes: u64,
managed_objects_peak: u64,
db_connections: u64,
db_operations: u64,
}
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct RuntimeDocument {
leaf_identity: String,
common_identities: [String; 3],
owner_generation: u64,
component_proof_identity: String,
expected_calibration_provenance: [String; 9],
solver_schema_identity: String,
admission_layout_identity: String,
build_costs: [[u64; 7]; 4],
support_limits: [u64; 4],
topology_constants: [u64; 3],
routes: Vec<RuntimeRouteDocument>,
}
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct RuntimeRouteDocument {
ordinal: u64,
route_id: u64,
framework_bytes: u64,
task_storage_bytes: u64,
response_carrier_bytes: u64,
}
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct CalibrationDocument {
leaf_identity: String,
common_identities: [String; 3],
owner_generation: u64,
provenance: [String; 9],
fixed_costs: [u64; 7],
allocator_costs: [u64; 2],
calibrated_constants: [u64; 3],
}
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct AdmissionDocument {
leaf_identity: String,
common_identities: [String; 3],
owner_generation: u64,
solver_schema_identity: String,
checked_relation_identity: String,
admission_layout_identity: String,
}
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct ObservabilityDocument {
leaf_identity: String,
common_identities: [String; 3],
owner_generation: u64,
machine_identity: String,
component_identities: [String; 4],
profile: [u64; 6],
config_schema_identity: String,
config_identity: String,
config_values: [u64; 5],
work_identity: String,
sizes: [u64; 4],
alignments: [u64; 4],
offsets: [u64; 4],
aggregate_layout: [u64; 2],
payload_machine_bytes: u64,
source_identity: String,
build_identity: String,
root_identity: String,
constituent_identity: String,
queue_state_layout: QueueStateLayoutDocument,
}
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct QueueStateLayoutDocument {
schema_identity: String,
type_identity: String,
target_identity: String,
size_bytes: u64,
alignment_bytes: u64,
block_count: u64,
reserve_bytes: u64,
authority_receipt_identity: String,
}
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct NormalizedDocument {
costs: [[u64; 7]; 5],
allocator_costs: [u64; 2],
support_limits: [u64; 4],
closure_constants: [u64; 6],
routes: Vec<NormalizedRouteDocument>,
observability_layout_digest_values: [u64; 20],
root_identity: String,
costs_attestation_identity: String,
support_attestation_identity: String,
route_set_attestation_identity: String,
}
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct NormalizedRouteDocument {
ordinal: u64,
route_id: u64,
managed_commitment_bytes: u64,
managed_objects_peak: u64,
framework_bytes: u64,
task_storage_bytes: u64,
response_carrier_bytes: u64,
db_connections: u64,
db_operations: u64,
}
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct TerminationDocument {
leaf_identity: String,
common_identities: [String; 3],
owner_generation: u64,
topology: [u64; 4],
topology_identity: String,
db_normal_return_work_identity: String,
writer_work_identity: String,
runtime_work_identity: String,
composed_identity: String,
}
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct CommitmentsDocument {
service_capacity: String,
runtime_capacity: String,
runtime_work: String,
admission_relation: String,
db_normal_return_work: String,
writer_work: String,
observability: String,
}
#[allow(clippy::result_large_err)]
pub fn verify_rendezvous_manifest_structural_preflight(
applicability: VerifiedRendezvousManifestKeyApplicabilityReceipt,
input: CanonicalSignedRendezvousManifestInput,
) -> Result<
StructurallyVerifiedRendezvousManifestPreflightOwner,
(
RendezvousManifestPreflightError,
VerifiedRendezvousManifestKeyApplicabilityReceipt,
CanonicalSignedRendezvousManifestInput,
),
> {
macro_rules! fail {
($error:expr) => {
return Err(($error, applicability, input))
};
}
if input.signature.len() != 64 {
fail!(RendezvousManifestPreflightError::Signature);
}
if applicability.domain != sha256(DOMAIN.as_bytes())
|| applicability.usage != sha256(USAGE.as_bytes())
|| sha256(&applicability.public_key) != applicability.key_identity
|| !distinct_authorities(&applicability)
{
fail!(RendezvousManifestPreflightError::Foreign);
}
let document: RendezvousManifestDocument = match serde_json::from_slice(&input.canonical) {
Ok(document) => document,
Err(_) => fail!(RendezvousManifestPreflightError::Encoding),
};
if serde_json::to_vec(&document).ok().as_deref() != Some(input.canonical.as_slice()) {
fail!(RendezvousManifestPreflightError::Encoding);
}
if document.schema != SCHEMA
|| document.signature_domain != DOMAIN
|| document.usage != USAGE
|| document.algorithm != "Ed25519"
|| document.owner_generation == 0
|| decode_identity(&document.key_identity) != Some(applicability.key_identity)
|| decode_identity(&document.authority_identity) != Some(applicability.authority_identity)
{
fail!(RendezvousManifestPreflightError::Foreign);
}
if UnparsedPublicKey::new(&ED25519, applicability.public_key)
.verify(&input.canonical, &input.signature)
.is_err()
{
fail!(RendezvousManifestPreflightError::Signature);
}
if !all_identities_are_canonical(&document) || !structural_shape_is_valid(&document) {
fail!(RendezvousManifestPreflightError::Shape);
}
Ok(StructurallyVerifiedRendezvousManifestPreflightOwner {
subject_identity: sha256(&input.canonical),
key_identity: applicability.key_identity,
authority_identity: applicability.authority_identity,
canonical: input.canonical,
signature: input.signature,
document,
})
}
fn distinct_authorities(value: &VerifiedRendezvousManifestKeyApplicabilityReceipt) -> bool {
let mut keys = Vec::with_capacity(9);
keys.push(value.key_identity);
keys.extend(value.other_key_identities);
let mut authorities = Vec::with_capacity(9);
authorities.push(value.authority_identity);
authorities.extend(value.other_authority_identities);
!keys.contains(&[0; 32])
&& !authorities.contains(&[0; 32])
&& keys
.iter()
.enumerate()
.all(|(index, item)| !keys[index + 1..].contains(item))
&& authorities
.iter()
.enumerate()
.all(|(index, item)| !authorities[index + 1..].contains(item))
}
fn structural_shape_is_valid(value: &RendezvousManifestDocument) -> bool {
let service = &value.leaves.service.routes;
let runtime = &value.leaves.runtime.routes;
let normalized = &value.normalized.routes;
if service.is_empty() || service.len() != runtime.len() || service.len() != normalized.len() {
return false;
}
for (index, ((service, runtime), normalized)) in
service.iter().zip(runtime).zip(normalized).enumerate()
{
let Ok(ordinal) = u64::try_from(index) else {
return false;
};
if service.ordinal != ordinal
|| runtime.ordinal != ordinal
|| normalized.ordinal != ordinal
|| service.route_id == 0
|| service.route_id != runtime.route_id
|| service.route_id != normalized.route_id
{
return false;
}
}
value.leaves.service.owner_generation == value.owner_generation
&& value.leaves.runtime.owner_generation == value.owner_generation
&& value.leaves.calibration.owner_generation == value.owner_generation
&& value.leaves.admission.owner_generation == value.owner_generation
&& value.leaves.observability.owner_generation == value.owner_generation
&& value.termination.owner_generation == value.owner_generation
&& value.leaves.service.common_identities == value.common_identities
&& value.leaves.runtime.common_identities == value.common_identities
&& value.leaves.calibration.common_identities == value.common_identities
&& value.leaves.admission.common_identities == value.common_identities
&& value.leaves.observability.common_identities == value.common_identities
&& value.termination.common_identities == value.common_identities
}
fn all_identities_are_canonical(document: &RendezvousManifestDocument) -> bool {
let Ok(value) = serde_json::to_value(document) else {
return false;
};
fn visit(key: Option<&str>, value: &serde_json::Value) -> bool {
match value {
serde_json::Value::Object(values) => {
values.iter().all(|(key, value)| visit(Some(key), value))
}
serde_json::Value::Array(values) => values.iter().all(|value| visit(key, value)),
serde_json::Value::String(value)
if key.is_some_and(|key| {
!matches!(key, "schema" | "signature_domain" | "usage" | "algorithm")
}) =>
{
decode_identity(value).is_some()
}
_ => true,
}
}
visit(None, &value)
}
fn decode_identity(value: &str) -> Option<[u8; 32]> {
if value.len() != 64
|| !value
.bytes()
.all(|byte| byte.is_ascii_digit() || (b'a'..=b'f').contains(&byte))
{
return None;
}
let mut output = [0; 32];
for (index, chunk) in value.as_bytes().chunks_exact(2).enumerate() {
output[index] = u8::from_str_radix(core::str::from_utf8(chunk).ok()?, 16).ok()?;
}
Some(output)
}
fn sha256(value: &[u8]) -> [u8; 32] {
digest(&SHA256, value)
.as_ref()
.try_into()
.expect("SHA-256 length")
}
#[cfg(test)]
mod tests {
include!("rendezvous_manifest_tests.rs");
}