#![allow(clippy::unwrap_used, clippy::pedantic, missing_docs)]
use std::{future::Future, pin::Pin, sync::Arc};
use axum::body::Body;
use http::{Request, StatusCode};
use http_body_util::BodyExt as _;
use polyc_a2a::{
AppState, InMemoryTaskStore, TurnOutcome, TurnRequest, TurnRunner,
UnconfiguredApprovalResponder,
card::{CardConfig, signed_card, verify_card},
router,
};
use polyc_crypto::Signer;
use polyc_runtime::admission::AdmissionGate;
use serde_json::Value;
use tower::ServiceExt as _;
struct NoopRunner;
impl TurnRunner for NoopRunner {
fn run_turn<'a>(
&'a self,
_req: TurnRequest,
) -> Pin<Box<dyn Future<Output = TurnOutcome> + Send + 'a>> {
Box::pin(async {
TurnOutcome::Completed {
text: String::new(),
}
})
}
}
fn state(signer: &Signer) -> AppState {
let card = signed_card(
&CardConfig {
name: "Polychrome".to_owned(),
description: "A polychrome deployment reachable over A2A.".to_owned(),
url: "https://agent.example/".to_owned(),
version: "0.1.3".to_owned(),
},
signer,
);
AppState {
card: Arc::new(card),
runner: Arc::new(NoopRunner),
approvals: Arc::new(UnconfiguredApprovalResponder),
store: Arc::new(InMemoryTaskStore::new()),
turn_limit: AdmissionGate::new(64),
peers: polyc_a2a::PeerAuthenticator::single("test-peer", "unused-by-agent-card-endpoint")
.unwrap(),
}
}
#[tokio::test]
async fn agent_card_is_v1_shaped_and_signed() {
let signer = Signer::from_seed(7);
let app = router(state(&signer));
let response = app
.oneshot(
Request::builder()
.uri("/.well-known/agent-card.json")
.body(Body::empty())
.unwrap(),
)
.await
.unwrap();
assert_eq!(response.status(), StatusCode::OK);
let body = response.into_body().collect().await.unwrap().to_bytes();
let card: Value = serde_json::from_slice(&body).unwrap();
assert_eq!(card["name"], "Polychrome");
assert_eq!(card["version"], "0.1.3");
assert!(card.get("url").is_none(), "v1.0 has no top-level url");
assert!(card.get("protocolVersion").is_none());
assert_eq!(
card["supportedInterfaces"][0]["url"],
"https://agent.example/"
);
assert_eq!(card["supportedInterfaces"][0]["protocolBinding"], "JSONRPC");
assert_eq!(card["supportedInterfaces"][0]["protocolVersion"], "1.0");
assert!(card["capabilities"].is_object());
assert!(card["capabilities"].get("stateTransitionHistory").is_none());
assert!(card["defaultInputModes"].as_array().is_some());
assert!(card["defaultOutputModes"].as_array().is_some());
assert!(
card["skills"]
.as_array()
.is_some_and(|skills| !skills.is_empty())
);
assert!(
card["signatures"]
.as_array()
.is_some_and(|sigs| !sigs.is_empty())
);
assert!(
verify_card(&card, &signer.public_key_bytes()),
"card signature must verify against the deployment principal"
);
}