polyc-state-connect 2026.9.0

State plane transport adapter: capability-specific Connect clients and server-trait glue mapping the generated wire types onto the polyc-state kernel — typed outcomes, per-call admission, and the conformance surface the authenticated shell proves itself against (docs/proposals/separated-planes.md).
//! Query-audit-specific outcomes carried as Connect details.

use connectrpc::{ConnectError, ErrorCode, ErrorDetail};
use polyc_proto::proto::polychrome::state::v1 as pb;
use polyc_state::{
    error::StateError,
    query_audit::{QueryAuditError, QueryId},
};

use crate::{
    error::{TransportFallback, decode_detail, from_connect_error as state_from_connect},
    wire::Kernel,
};

/// The detail type for outcomes added by the query-audit family.
pub const QUERY_AUDIT_ERROR_DETAIL_TYPE: &str = "polychrome.state.v1.QueryAuditErrorDetail";

impl From<Kernel<&QueryAuditError>> for pb::QueryAuditErrorDetail {
    fn from(value: Kernel<&QueryAuditError>) -> Self {
        use pb::__buffa::oneof::query_audit_error_detail::Outcome;
        let outcome = match value.0 {
            QueryAuditError::State(error) => {
                Outcome::from(pb::StateErrorDetail::from(Kernel(error)))
            }
            QueryAuditError::NoRecordedIntent { query } => {
                Outcome::from(pb::NoRecordedQueryIntentDetail {
                    query: query.as_str().to_owned(),
                    __buffa_unknown_fields: buffa::UnknownFields::default(),
                })
            }
        };
        Self {
            outcome: Some(outcome),
            __buffa_unknown_fields: buffa::UnknownFields::default(),
        }
    }
}

impl TryFrom<pb::QueryAuditErrorDetail> for Kernel<QueryAuditError> {
    type Error = pb::QueryAuditErrorDetail;

    fn try_from(value: pb::QueryAuditErrorDetail) -> Result<Self, Self::Error> {
        use pb::__buffa::oneof::query_audit_error_detail::Outcome;
        let Some(outcome) = value.outcome.clone() else {
            return Err(value);
        };
        match outcome {
            Outcome::State(detail) => Kernel::<StateError>::try_from(*detail)
                .map(|error| Self(QueryAuditError::State(error.into_inner())))
                .map_err(|_| value),
            Outcome::NoRecordedIntent(detail) => Ok(Self(QueryAuditError::NoRecordedIntent {
                query: QueryId::new(detail.query),
            })),
        }
    }
}

/// Encodes the exact query-audit outcome.
#[must_use]
pub fn to_connect_error(error: &QueryAuditError) -> ConnectError {
    let code = match error {
        QueryAuditError::State(state) => crate::error::code_for(state),
        QueryAuditError::NoRecordedIntent { .. } => ErrorCode::FailedPrecondition,
    };
    ConnectError::new(code, error.to_string()).with_detail(ErrorDetail::from_message(
        QUERY_AUDIT_ERROR_DETAIL_TYPE,
        &pb::QueryAuditErrorDetail::from(Kernel(error)),
    ))
}

/// Decodes a query-audit detail, or falls back to the shared State outcome.
#[must_use]
pub fn from_connect_error(error: &ConnectError, fallback: &TransportFallback) -> QueryAuditError {
    for detail in &error.details {
        if detail.type_url != QUERY_AUDIT_ERROR_DETAIL_TYPE {
            continue;
        }
        let Some(encoded) = detail.value.as_deref() else {
            continue;
        };
        let Ok(bytes) = decode_detail(encoded) else {
            continue;
        };
        let Ok(message) = <pb::QueryAuditErrorDetail as buffa::Message>::decode_from_slice(&bytes)
        else {
            continue;
        };
        if let Ok(typed) = Kernel::<QueryAuditError>::try_from(message) {
            return typed.into_inner();
        }
    }
    QueryAuditError::State(state_from_connect(error, fallback))
}

#[cfg(test)]
mod tests {
    use super::*;
    use polyc_state::query_audit;

    #[test]
    fn no_intent_round_trips_as_its_own_variant() {
        let original = QueryAuditError::NoRecordedIntent {
            query: QueryId::new("q"),
        };
        let wire = to_connect_error(&original);
        let back = from_connect_error(
            &wire,
            &TransportFallback::new(query_audit::family(), 65_536, 1),
        );
        assert_eq!(back, original);
    }
}