heddle-cli-contract 0.24.2

Heddle's CLI verb catalog, schemas, help, and recovery contract.
// SPDX-License-Identifier: Apache-2.0
//! Wire payloads for `auth`, `whoami`, and `identity`.
//!
//! These payloads are emitted by `hosted-client`, which sits above this
//! crate; the types live here so the schema registry registers the real
//! serialization structs.

use schemars::JsonSchema;
use serde::Serialize;

/// JSON payload for `heddle promote`.
#[derive(Debug, Serialize, JsonSchema)]
#[schemars(rename = "PromoteSchema")]
pub struct PromoteOutput {
    pub output_kind: &'static str,
    pub status: &'static str,
    pub from: String,
    pub full_path: String,
    pub spool_id: String,
    pub is_repo: bool,
    pub server: String,
    pub recommended_action: Option<String>,
}

/// JSON payload for `heddle grant create`.
#[derive(Debug, Serialize, JsonSchema)]
#[schemars(rename = "GrantCreateSchema")]
pub struct GrantCreateOutput {
    pub output_kind: &'static str,
    pub id: String,
    pub principal: String,
    pub role: String,
    pub spool: String,
    pub server: String,
    pub recommended_action: Option<String>,
}

/// One row from `heddle grant list`.
#[derive(Debug, Serialize, JsonSchema)]
#[schemars(rename = "GrantRowSchema")]
pub struct GrantRowOutput {
    pub id: String,
    pub principal: String,
    pub role: String,
    pub spool: String,
}

/// JSON payload for `heddle grant list`.
#[derive(Debug, Serialize, JsonSchema)]
#[schemars(rename = "GrantListSchema")]
pub struct GrantListOutput {
    pub output_kind: &'static str,
    pub spool: String,
    pub server: String,
    pub grants: Vec<GrantRowOutput>,
    pub recommended_action: Option<String>,
}

/// JSON payload for `heddle grant delete`.
#[derive(Debug, Serialize, JsonSchema)]
#[schemars(rename = "GrantDeleteSchema")]
pub struct GrantDeleteOutput {
    pub output_kind: &'static str,
    pub id: String,
    pub principal: String,
    pub spool: String,
    pub server: String,
    pub deleted: bool,
    pub recommended_action: Option<String>,
}

#[derive(Debug, Serialize, JsonSchema)]
#[schemars(rename = "AgentAccountCreatedSchema")]
pub struct AgentAccountCreatedOutput {
    pub output_kind: &'static str,
    pub account_id: String,
    pub pet_name: String,
    /// Subject carried by the client-minted, persisted agent capability.
    pub subject: String,
    pub authenticated: bool,
    pub credential_saved: bool,
    pub next: HumanPromotionDirective,
}

#[derive(Debug, Serialize, JsonSchema)]
pub struct HumanPromotionDirective {
    pub kind: &'static str,
    pub summary: &'static str,
    pub account_id: String,
    /// Agent-native command that starts the short-lived human claim ceremony.
    pub command: &'static str,
    /// Reserved for a concrete server-provided promotion affordance.
    pub promotion_uri: Option<String>,
}

/// How a server's descriptor trust was established.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, JsonSchema)]
#[serde(rename_all = "lowercase")]
pub enum DescriptorTrustSource {
    Explicit,
    Automatic,
}

#[derive(Serialize, JsonSchema)]
#[schemars(rename = "AuthLogoutSchema")]
pub struct AuthLogoutOutput {
    pub output_kind: &'static str,
    pub server: String,
    pub removed: bool,
    /// Whether a device signing identity recorded for this server (heddle#482)
    /// was removed. `false` when none was linked; on a removal failure logout
    /// errors instead of emitting this output, so a `true` here always means
    /// the logged-out private key is no longer on disk.
    pub device_identity_removed: bool,
}

#[derive(Serialize, JsonSchema)]
#[schemars(rename = "AuthStatusSchema")]
pub struct AuthStatusOutput {
    pub output_kind: &'static str,
    pub server: String,
    pub authenticated: bool,
    /// Credential origin: `env:<path>` when `HEDDLE_CREDENTIAL` is set,
    /// `keystore` for a stored credential, `none` when unauthenticated.
    pub source: String,
    pub proof_key_available: bool,
    pub subject: Option<String>,
    pub credential_id: Option<String>,
    pub expires_at: Option<String>,
    pub recommended_action: Option<String>,
}

#[derive(Serialize, JsonSchema)]
#[schemars(rename = "AuthTrustSchema")]
pub struct AuthTrustOutput {
    pub output_kind: &'static str,
    pub canonical_server: String,
    /// `explicit` or `automatic`.
    pub source: DescriptorTrustSource,
    pub key_id: String,
    pub public_key: String,
    pub fingerprint: String,
}

#[derive(Serialize, JsonSchema)]
#[schemars(rename = "AuthCreateServiceTokenSchema")]
pub struct ServiceTokenOutput {
    pub output_kind: &'static str,
    pub name: String,
    pub scope: String,
    /// Absolute path of the `.hcred` credential file written with mode 0600.
    /// The token and proof key never appear on stdout or in JSON.
    pub credential_path: String,
    pub expires_in_days: u32,
}

#[derive(Serialize, JsonSchema)]
#[schemars(rename = "AuthSignupInviteCreatedSchema")]
pub struct SignupInviteCreatedOutput {
    pub output_kind: &'static str,
    pub invite_id: String,
    /// One-time bearer material, returned only by the creation response.
    pub redemption_secret: String,
    pub allowance_remaining: Option<u32>,
}

#[derive(Serialize, JsonSchema)]
#[schemars(rename = "AuthSignupInviteSchema")]
pub struct SignupInviteOutput {
    pub invite_id: String,
    pub status: String,
    pub bound_email: Option<String>,
    pub expires_at: Option<String>,
}

#[derive(Serialize, JsonSchema)]
#[schemars(rename = "AuthSignupInviteListSchema")]
pub struct SignupInviteListOutput {
    pub output_kind: &'static str,
    pub invites: Vec<SignupInviteOutput>,
    pub allowance_remaining: Option<u32>,
}

// ---- whoami ----------------------------------------------------------------

#[derive(Debug, Clone, Serialize, JsonSchema)]
#[schemars(rename = "WhoamiCaptureActorSchema")]
pub struct CaptureActor {
    pub name: String,
    pub email: String,
    /// `environment`, `repository`, `git_config`, `user_config`, or null when unknown.
    pub source: Option<&'static str>,
}

#[derive(Debug, Serialize, JsonSchema)]
#[schemars(rename = "WhoamiSchema")]
pub struct WhoamiOutput {
    pub output_kind: &'static str,
    /// Who the next capture is attributed to. Distinct from hosted auth.
    pub capture_actor: CaptureActor,
    pub server: String,
    /// A usable credential resolves for this server.
    pub authenticated: bool,
    /// Credential origin: `env:<path>`, `keystore`, or `none`.
    pub source: String,
    /// Locally verified subject, present even when the server is unreachable.
    pub subject: Option<String>,
    /// The server answered native `ObserveIdentity` with the current credential.
    pub reachable: bool,
    /// Locally inferred credential class, replaced by the observed v2 class
    /// when the server is reachable. `None` when unauthenticated.
    pub token_kind: Option<String>,
    /// Resource scopes the delegation chain restricts this token to. Empty ⇒
    /// full resource authority.
    pub scopes: Vec<String>,
    /// The intersected hosted-operation ceiling from the delegation chain.
    /// `None` ⇒ no operation allowlist (full authority).
    pub operation_ceiling: Option<Vec<String>>,
    /// Effective token expiry (RFC3339). `None` ⇒ no expiry recorded.
    pub expires_at: Option<String>,
    /// Seconds until `expires_at`; negative when already expired.
    pub ttl_seconds_remaining: Option<i64>,
    /// The device proof key needed to sign hosted requests is present and valid.
    pub proof_key_available: bool,
    /// Server-authoritative identity, present only when `reachable`.
    pub identity: Option<WhoamiIdentity>,
    /// Grant-reachable hosted paths as `spool/<handle>/<name>`.
    /// Empty when unauthenticated, unreachable, or ListSpools was unavailable.
    pub spools: Vec<String>,
    pub recommended_action: Option<String>,
}

#[derive(Debug, Serialize, JsonSchema)]
#[schemars(rename = "WhoamiIdentitySchema")]
pub struct WhoamiIdentity {
    pub principal_id: String,
    pub account_id: String,
    pub handle: Option<String>,
    pub acting_agent_id: Option<String>,
    pub rooting_tier: String,
    pub credential_id: Option<String>,
    pub credential_subject: String,
    pub credential_kind: String,
    pub session_id: Option<String>,
    pub authentication_methods: Vec<String>,
    pub agent_provider: Option<String>,
    pub agent_model: Option<String>,
    /// Verified method hints from the current credential observation.
    pub available_actions: Vec<String>,
}