pub mod claim_secret;
pub mod state_machine;
pub mod token;
pub use state_machine::{
InstallTokenState, InstallTokenStore, PendingBreakGlassAcl, PendingEmergencyBootstrap,
StartClaimOutcome,
};
pub use token::{
INSTALL_AUDIENCE, INSTALL_SESSION_AUDIENCE, INSTALL_SESSION_DEFAULT_TTL_SECS, INSTALL_SUBJECT,
INSTALL_TOKEN_DEFAULT_TTL_SECS, InstallSessionClaims, InstallTokenClaims, InstallTokenSigner,
mint_install_session_token, mint_install_token, parse_install_token,
};
use tokio::sync::Mutex;
pub static INSTALL_TOKEN_LOCK: Mutex<()> = Mutex::const_new(());
#[doc(hidden)]
pub use INSTALL_TOKEN_LOCK as INSTALL_CARVEOUT_LOCK;
pub async fn record_offline_acl_write(
store: &vti_common::store::Store,
command: &str,
action: &str,
did: &str,
role: Option<&crate::acl::VtcRole>,
contexts: &[String],
) -> Result<(), vti_common::error::AppError> {
let install = InstallTokenStore::new(store.keyspace(crate::store::keyspaces::INSTALL)?);
let now = crate::auth::session::now_epoch();
let admins = crate::acl::list_acl_entries(&store.keyspace(crate::store::keyspaces::ACL)?)
.await?
.into_iter()
.filter(|e| e.admin.is_administrator() && !e.is_expired(now))
.map(|e| e.did)
.collect();
install
.record_break_glass(&PendingBreakGlassAcl {
command: command.to_string(),
action: action.to_string(),
did: did.to_string(),
role: role.map(|r| r.to_string()).unwrap_or_default(),
contexts: contexts.to_vec(),
operator_hostname: gethostname::gethostname().to_string_lossy().into_owned(),
invoked_at: chrono::Utc::now(),
admins,
})
.await
}