devboy_clickup/liveness.rs
1//! ClickUp [`LivenessProbe`] stub per [ADR-021] §6.
2//!
3//! ClickUp's introspection endpoint is `GET /api/v2/user`, but
4//! routing the response through the typed liveness shape (active /
5//! revoked / expired) requires more sniffing than this commit's
6//! scope allows. The stub uses the trait's default `test` impl
7//! (which returns [`LivenessStatus::NotImplemented`]) and wires
8//! the provider name so `doctor` shows
9//! "clickup liveness probe is not implemented; format-only
10//! validation only" instead of "no probe configured".
11//!
12//! Replacing the stub: drop a real `test` override against
13//! `<base>/api/v2/user`, mirroring `crates/plugins/api/github`.
14//!
15//! [ADR-021]: https://github.com/meteora-pro/devboy-tools/blob/main/docs/architecture/adr/ADR-021-external-secret-sources.md
16//! [`LivenessStatus::NotImplemented`]: devboy_core::liveness::LivenessStatus
17
18use async_trait::async_trait;
19use devboy_core::LivenessProbe;
20
21use crate::client::ClickUpClient;
22
23#[async_trait]
24impl LivenessProbe for ClickUpClient {
25 fn provider_name(&self) -> &str {
26 "clickup"
27 }
28}
29
30#[cfg(test)]
31mod tests {
32 use super::*;
33 use devboy_core::liveness::LivenessStatus;
34 use secrecy::SecretString;
35
36 #[tokio::test]
37 async fn provider_name_is_clickup_and_default_returns_not_implemented() {
38 let client = ClickUpClient::new("list-id", SecretString::from("any".to_owned()));
39 assert_eq!(client.provider_name(), "clickup");
40 let r = client
41 .test(&SecretString::from("any".to_owned()))
42 .await
43 .unwrap();
44 assert_eq!(r.status, LivenessStatus::NotImplemented);
45 assert!(r.detail.unwrap().contains("clickup"));
46 }
47}