use std::collections::{BTreeMap, BTreeSet};
use meerkat_core::ToolCategoryOverride;
use meerkat_core::service::{
MobToolAuthorityContext, MobToolCallerProvenance, OpaquePrincipalToken,
};
use crate::meerkat_machine::dsl;
struct GeneratedAuthorityBridgeToken;
static GENERATED_AUTHORITY_BRIDGE_TOKEN: GeneratedAuthorityBridgeToken =
GeneratedAuthorityBridgeToken;
fn generated_authority_bridge_token() -> &'static (dyn std::any::Any + Send + Sync) {
&GENERATED_AUTHORITY_BRIDGE_TOKEN
}
#[doc(hidden)]
#[allow(improper_ctypes_definitions, unsafe_code)]
#[unsafe(export_name = concat!(
"__meerkat_runtime_generated_authority_bridge_token_is_valid_v1_mob_operator_authority_",
env!("MEERKAT_GENERATED_AUTHORITY_BRIDGE_SYMBOL_SUFFIX")
))]
pub extern "Rust" fn generated_authority_bridge_token_is_valid(
token: &(dyn std::any::Any + Send + Sync),
) -> bool {
token.is::<GeneratedAuthorityBridgeToken>()
}
#[allow(improper_ctypes_definitions, unsafe_code)]
unsafe extern "Rust" {
#[link_name = concat!(
"__meerkat_core_runtime_generated_mob_tool_authority_context_build_v1_",
env!("MEERKAT_GENERATED_AUTHORITY_BRIDGE_SYMBOL_SUFFIX")
)]
fn core_generated_mob_tool_authority_context_build(
token: &'static (dyn std::any::Any + Send + Sync),
principal_token: OpaquePrincipalToken,
can_create_mobs: bool,
can_mutate_profiles: bool,
can_run_adaptive_packs: bool,
managed_mob_scope: BTreeSet<String>,
spawn_profile_scope: BTreeMap<String, BTreeSet<String>>,
caller_provenance: Option<MobToolCallerProvenance>,
audit_invocation_id: Option<String>,
) -> Result<MobToolAuthorityContext, String>;
}
pub fn resolve_mob_operator_access(
enable_mob: ToolCategoryOverride,
persisted_authority_context: Option<MobToolAuthorityContext>,
) -> (ToolCategoryOverride, Option<MobToolAuthorityContext>) {
if matches!(enable_mob, ToolCategoryOverride::Disable) {
return (ToolCategoryOverride::Disable, None);
}
if let Some(authority_context) = persisted_authority_context {
return match restore_mob_operator_authority(&authority_context) {
Ok(authority_context) => (ToolCategoryOverride::Enable, Some(authority_context)),
Err(error) => {
tracing::warn!(
error = %error,
"generated mob operator authority rejected persisted context"
);
(ToolCategoryOverride::Disable, None)
}
};
}
match resolve_requested_mob_operator_authority(enable_mob) {
Ok(Some(authority_context)) => (ToolCategoryOverride::Enable, Some(authority_context)),
Ok(None) => (enable_mob, None),
Err(error) => {
tracing::warn!(
error = %error,
"generated mob operator authority rejected access request"
);
(ToolCategoryOverride::Disable, None)
}
}
}
pub fn create_only_mob_operator_authority() -> Result<MobToolAuthorityContext, String> {
resolve_requested_mob_operator_authority(ToolCategoryOverride::Enable)?
.ok_or_else(|| "generated mob operator authority omitted explicit enablement".to_string())
}
fn resolve_requested_mob_operator_authority(
enable_mob: ToolCategoryOverride,
) -> Result<Option<MobToolAuthorityContext>, String> {
let request_kind = match enable_mob {
ToolCategoryOverride::Enable => dsl::MobOperatorAccessRequestKind::Enable,
ToolCategoryOverride::Disable => dsl::MobOperatorAccessRequestKind::Disable,
ToolCategoryOverride::Inherit => dsl::MobOperatorAccessRequestKind::Inherit,
};
let mut authority = fresh_authority();
apply(
&mut authority,
dsl::MeerkatMachineInput::ResolveMobOperatorCreateAuthority {
request_kind,
principal_token: OpaquePrincipalToken::generated(),
caller_provenance: None,
audit_invocation_id: None,
},
)?;
if authority.state().mob_operator_authority_present {
context_from_authority_state(authority.state()).map(Some)
} else {
Ok(None)
}
}
pub fn restore_mob_operator_authority(
authority_context: &MobToolAuthorityContext,
) -> Result<MobToolAuthorityContext, String> {
let mut authority = fresh_authority();
apply_restore(&mut authority, authority_context, None, None)?;
context_from_authority_state(authority.state())
}
pub fn set_create_authority(
authority_context: &MobToolAuthorityContext,
allowed: bool,
) -> Result<MobToolAuthorityContext, String> {
let mut authority = authority_from_context(authority_context)?;
apply(
&mut authority,
dsl::MeerkatMachineInput::SetMobOperatorCreateAuthority { allowed },
)?;
context_from_authority_state(authority.state())
}
pub fn set_profile_mutation(
authority_context: &MobToolAuthorityContext,
allowed: bool,
) -> Result<MobToolAuthorityContext, String> {
let mut authority = authority_from_context(authority_context)?;
apply(
&mut authority,
dsl::MeerkatMachineInput::SetMobOperatorProfileMutation { allowed },
)?;
context_from_authority_state(authority.state())
}
pub fn grant_manage_mob(
authority_context: &MobToolAuthorityContext,
mob_id: impl Into<String>,
) -> Result<MobToolAuthorityContext, String> {
let mut authority = authority_from_context(authority_context)?;
apply(
&mut authority,
dsl::MeerkatMachineInput::GrantMobOperatorManageMob {
mob_id: mob_id.into(),
},
)?;
context_from_authority_state(authority.state())
}
pub fn grant_spawn_profile_in_mob(
authority_context: &MobToolAuthorityContext,
mob_id: impl Into<String>,
profile: impl Into<String>,
) -> Result<MobToolAuthorityContext, String> {
grant_spawn_profiles_in_mob(authority_context, mob_id, [profile.into()])
}
pub fn grant_spawn_profiles_in_mob<I, S>(
authority_context: &MobToolAuthorityContext,
mob_id: impl Into<String>,
profiles: I,
) -> Result<MobToolAuthorityContext, String>
where
I: IntoIterator<Item = S>,
S: Into<String>,
{
let mut authority = authority_from_context(authority_context)?;
apply(
&mut authority,
dsl::MeerkatMachineInput::SetMobOperatorSpawnProfilesInMob {
mob_id: mob_id.into(),
profiles: profiles.into_iter().map(Into::into).collect(),
},
)?;
context_from_authority_state(authority.state())
}
pub fn with_caller_provenance(
authority_context: &MobToolAuthorityContext,
caller_provenance: MobToolCallerProvenance,
) -> Result<MobToolAuthorityContext, String> {
let mut authority = fresh_authority();
apply_restore(
&mut authority,
authority_context,
Some(Some(caller_provenance)),
None,
)?;
context_from_authority_state(authority.state())
}
pub fn with_audit_invocation_id(
authority_context: &MobToolAuthorityContext,
audit_invocation_id: impl Into<String>,
) -> Result<MobToolAuthorityContext, String> {
let mut authority = fresh_authority();
apply_restore(
&mut authority,
authority_context,
None,
Some(Some(audit_invocation_id.into())),
)?;
context_from_authority_state(authority.state())
}
fn fresh_authority() -> dsl::MeerkatMachineAuthority {
dsl::MeerkatMachineAuthority::new()
}
fn authority_from_context(
authority_context: &MobToolAuthorityContext,
) -> Result<dsl::MeerkatMachineAuthority, String> {
let mut authority = fresh_authority();
apply_restore(&mut authority, authority_context, None, None)?;
Ok(authority)
}
#[allow(clippy::option_option)]
fn apply_restore(
authority: &mut dsl::MeerkatMachineAuthority,
authority_context: &MobToolAuthorityContext,
caller_provenance: Option<Option<MobToolCallerProvenance>>,
audit_invocation_id: Option<Option<String>>,
) -> Result<(), String> {
if !authority_context.is_generated_authority_context() {
return Err("mob operator authority context was not minted by generated authority".into());
}
apply(
authority,
dsl::MeerkatMachineInput::RestoreMobOperatorAuthority {
principal_token: authority_context.principal_token().clone(),
can_create_mobs: authority_context.can_create_mobs(),
can_mutate_profiles: authority_context.can_mutate_profiles(),
managed_mob_scope: authority_context.managed_mob_scope().clone(),
spawn_profile_scope: authority_context.spawn_profile_scope().clone(),
caller_provenance: caller_provenance
.unwrap_or_else(|| authority_context.caller_provenance().cloned()),
audit_invocation_id: audit_invocation_id
.unwrap_or_else(|| authority_context.audit_invocation_id().map(str::to_owned)),
},
)
}
fn apply(
authority: &mut dsl::MeerkatMachineAuthority,
input: dsl::MeerkatMachineInput,
) -> Result<(), String> {
dsl::MeerkatMachineMutator::apply(authority, input)
.map(|_| ())
.map_err(|error| format!("MeerkatMachine rejected mob operator authority input: {error}"))
}
fn context_from_authority_state(
state: &dsl::MeerkatMachineState,
) -> Result<MobToolAuthorityContext, String> {
if !state.mob_operator_authority_present {
return Err("generated mob operator authority is absent".into());
}
let principal_token = state
.mob_operator_principal_token
.clone()
.ok_or_else(|| "generated mob operator authority omitted principal token".to_string())?;
#[allow(unsafe_code)]
unsafe {
core_generated_mob_tool_authority_context_build(
generated_authority_bridge_token(),
principal_token,
state.mob_operator_can_create_mobs,
state.mob_operator_can_mutate_profiles,
false,
state.mob_operator_managed_mob_scope.clone(),
state.mob_operator_spawn_profile_scope.clone(),
state.mob_operator_caller_provenance.clone(),
state.mob_operator_audit_invocation_id.clone(),
)
}
}
#[cfg(test)]
mod tests {
use super::*;
fn persisted_projection(authority_context: MobToolAuthorityContext) -> MobToolAuthorityContext {
serde_json::from_value(
serde_json::to_value(authority_context)
.expect("generated mob authority context must serialize"),
)
.expect("persisted mob authority projection must deserialize")
}
#[test]
fn persisted_mob_authority_projection_does_not_restore_behavior_authority() {
let authority = create_only_mob_operator_authority()
.expect("generated authority should allow explicit create request");
let authority = grant_manage_mob(&authority, "mob-1")
.expect("generated authority should accept manage scope grant");
let authority = grant_spawn_profile_in_mob(&authority, "mob-2", "investigator")
.expect("generated authority should accept spawn-profile scope grant");
let authority = with_caller_provenance(
&authority,
MobToolCallerProvenance::default().with_mob_id("mob-1"),
)
.expect("generated authority should accept caller provenance");
let authority = with_audit_invocation_id(&authority, "audit-1")
.expect("generated authority should accept audit invocation id");
let projected = persisted_projection(authority);
assert!(!projected.is_generated_authority_context());
assert!(!projected.can_create_mobs());
assert!(!projected.can_manage_mob("mob-1"));
let (override_mob, restored) =
resolve_mob_operator_access(ToolCategoryOverride::Enable, Some(projected));
assert_eq!(override_mob, ToolCategoryOverride::Disable);
assert!(restored.is_none());
}
#[test]
fn persisted_mob_authority_projection_cannot_drive_live_mutation() {
let authority = create_only_mob_operator_authority()
.expect("generated authority should allow explicit create request");
let projected = persisted_projection(authority);
let error = grant_manage_mob(&projected, "mob-1")
.expect_err("unsealed projection must not drive live authority mutation");
assert!(
error.contains("was not minted by generated authority"),
"unexpected error: {error}"
);
}
}