use base64::Engine;
use base64::engine::general_purpose::URL_SAFE_NO_PAD;
use serde::{Deserialize, Serialize};
use auths_core::ports::clock::ClockProvider;
use auths_core::signing::{PassphraseProvider, SecureSigner};
use auths_core::storage::keychain::KeyAlias;
use crate::domains::identity::error::SetupError;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PlatformClaim {
#[serde(rename = "type")]
pub claim_type: String,
pub platform: String,
pub namespace: String,
pub did: String,
pub timestamp: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub signature: Option<String>,
}
pub fn create_platform_claim(
platform: &str,
namespace: &str,
did: &str,
key_alias: &KeyAlias,
signer: &dyn SecureSigner,
passphrase_provider: &dyn PassphraseProvider,
clock: &dyn ClockProvider,
) -> Result<String, SetupError> {
let mut claim = PlatformClaim {
claim_type: "platform_claim".to_string(),
platform: platform.to_string(),
namespace: namespace.to_string(),
did: did.to_string(),
timestamp: clock.now().to_rfc3339(),
signature: None,
};
let unsigned_json = serde_json::to_value(&claim)
.map_err(|e| SetupError::PlatformVerificationFailed(format!("serialize claim: {e}")))?;
let canonical = json_canon::to_string(&unsigned_json)
.map_err(|e| SetupError::PlatformVerificationFailed(format!("canonicalize claim: {e}")))?;
let signature_bytes = signer
.sign_with_alias(key_alias, passphrase_provider, canonical.as_bytes())
.map_err(|e| SetupError::PlatformVerificationFailed(format!("sign claim: {e}")))?;
claim.signature = Some(URL_SAFE_NO_PAD.encode(&signature_bytes));
serde_json::to_string_pretty(&claim)
.map_err(|e| SetupError::PlatformVerificationFailed(format!("serialize signed claim: {e}")))
}