bijux-dag-runtime 0.4.1

Execution engine, replay semantics, and runtime policy layer for Bijux DAG graphs.
Documentation
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ApiVersion {
    pub major: u16,
    pub minor: u16,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Pagination {
    pub limit: usize,
    pub cursor: Option<String>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Page<T> {
    pub items: Vec<T>,
    pub next_cursor: Option<String>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ListFilter {
    pub field: String,
    pub value: String,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct VersionedResource {
    pub resource_version: u64,
    pub etag: String,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct DagResource {
    pub dag_id: String,
    pub logical_name: String,
    pub owner: String,
    pub tags: Vec<String>,
    pub version: VersionedResource,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct DagVersionResource {
    pub dag_id: String,
    pub version_id: String,
    pub status: String,
    pub compatibility_line: String,
    pub version: VersionedResource,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct RunResource {
    pub run_id: String,
    pub dag_id: String,
    pub dag_version_id: String,
    pub status: String,
    pub submitted_unix_ms: u128,
    pub version: VersionedResource,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct NodeAttemptResource {
    pub run_id: String,
    pub node_id: String,
    pub attempt: u32,
    pub status: String,
    pub started_unix_ms: u128,
    pub finished_unix_ms: Option<u128>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ArtifactResource {
    pub artifact_id: String,
    pub run_id: String,
    pub producer_node_id: String,
    pub schema_name: String,
    pub schema_version: String,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ScheduleResource {
    pub schedule_id: String,
    pub dag_id: String,
    pub trigger_kind: String,
    pub queue: String,
    pub suspended: bool,
    pub version: VersionedResource,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct QueueResource {
    pub queue_id: String,
    pub tenant: Option<String>,
    pub priority_policy: String,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PolicyResource {
    pub policy_id: String,
    pub domain: String,
    pub version: String,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AuditEventResource {
    pub audit_id: String,
    pub actor: String,
    pub action: String,
    pub resource: String,
    pub unix_ms: u128,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum RegistryOperation {
    Publish,
    Validate,
    Activate,
    Deprecate,
    Retire,
    Inspect,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum RunControlApiOperation {
    Submit,
    Cancel,
    Pause,
    Resume,
    Retry,
    Replay,
    Verify,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum ArtifactApiOperation {
    Inspect,
    Export,
    Verify,
    Lineage,
    RetentionAction,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum ScheduleApiOperation {
    Create,
    Update,
    Suspend,
    Preview,
    Audit,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct TypedApiRequest {
    pub api_version: ApiVersion,
    pub operation: String,
    pub request_id: String,
    pub payload: serde_json::Value,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct TypedApiResponse {
    pub api_version: ApiVersion,
    pub accepted: bool,
    pub status: String,
    pub response_id: String,
    pub payload: serde_json::Value,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum AuthenticationPrincipal {
    CliUser { subject: String },
    ServiceAccount { service: String },
    WorkerIdentity { worker_id: String },
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AuthContext {
    pub principal: AuthenticationPrincipal,
    pub scopes: Vec<String>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AuthorizationRule {
    pub resource_prefix: String,
    pub allowed_actions: Vec<String>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct EnvironmentScopedConfiguration {
    pub environment: String,
    pub values: BTreeMap<String, String>,
    pub overlays: BTreeMap<String, String>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct EventSubscription {
    pub subscription_id: String,
    pub topic: String,
    pub endpoint: String,
    pub active: bool,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ApiCompatibilityRule {
    pub min_supported_major: u16,
    pub max_supported_major: u16,
    pub supports_minor_additive_fields: bool,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ClientSdkShape {
    pub sdk_name: String,
    pub operations: Vec<String>,
    pub typed_models: bool,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ServiceArchitectureNote {
    pub api_boundary: String,
    pub scheduler_boundary: String,
    pub registry_boundary: String,
    pub executor_boundary: String,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ControlPlaneMvpDefinition {
    pub includes_registry: bool,
    pub includes_run_control: bool,
    pub includes_schedule_management: bool,
    pub includes_audit_log: bool,
    pub excludes_distributed_orchestration: bool,
}

pub fn paginate<T: Clone>(items: &[T], pagination: &Pagination) -> Page<T> {
    let start = pagination
        .cursor
        .as_ref()
        .and_then(|v| v.parse::<usize>().ok())
        .unwrap_or(0)
        .min(items.len());
    let end = (start + pagination.limit.max(1)).min(items.len());
    let next_cursor = if end < items.len() { Some(end.to_string()) } else { None };
    Page { items: items[start..end].to_vec(), next_cursor }
}

pub fn filter_resources<T>(
    items: Vec<T>,
    filter: &ListFilter,
    value_of: impl Fn(&T, &str) -> Option<String>,
) -> Vec<T> {
    items
        .into_iter()
        .filter(|item| value_of(item, &filter.field).as_deref() == Some(filter.value.as_str()))
        .collect()
}

pub fn authorize(auth: &AuthContext, action: &str, rules: &[AuthorizationRule]) -> bool {
    rules.iter().any(|rule| {
        auth.scopes.iter().any(|scope| scope.starts_with(&rule.resource_prefix))
            && rule.allowed_actions.iter().any(|a| a == action)
    })
}

pub fn check_api_compatibility(version: &ApiVersion, rule: &ApiCompatibilityRule) -> bool {
    version.major >= rule.min_supported_major && version.major <= rule.max_supported_major
}