properly handling patch updates
Some checks failed
CI / Clippy (push) Failing after 3m6s
CI / Rustfmt (push) Failing after 3m9s
CI / Cargo Audit & Deny (push) Successful in 5m2s
CI / Tests (push) Successful in 8m15s
CI / Security Blocking Checks (push) Successful in 10s
CI / Web Advisory Checks (push) Successful in 1m4s
CI / Web Blocking Checks (push) Failing after 4m52s
Publish Images And Chart / Resolve Publish Metadata (push) Successful in 2s
CI / Security Advisory Checks (push) Successful in 1m31s
Publish Images And Chart / Publish init-user (push) Failing after 30s
Publish Images And Chart / Publish init-packs (push) Failing after 1m41s
Publish Images And Chart / Publish migrations (push) Failing after 10s
Publish Images And Chart / Publish web (push) Failing after 11s
Publish Images And Chart / Publish sensor (push) Failing after 32s
Publish Images And Chart / Publish worker (push) Failing after 11s
Publish Images And Chart / Publish executor (push) Failing after 11s
Publish Images And Chart / Publish notifier (push) Failing after 9s
Publish Images And Chart / Publish api (push) Failing after 31s
Publish Images And Chart / Publish Helm Chart (push) Has been skipped

This commit is contained in:
2026-03-17 12:17:58 -05:00
parent 643023b6d5
commit f96861d417
136 changed files with 3782 additions and 1553 deletions

View File

@@ -76,9 +76,8 @@ pub struct UpdateActionRequest {
#[schema(example = 1)] #[schema(example = 1)]
pub runtime: Option<i64>, pub runtime: Option<i64>,
/// Optional semver version constraint for the runtime (e.g., ">=3.12", ">=3.12,<4.0", "~18.0") /// Optional semver version constraint patch for the runtime.
#[schema(example = ">=3.12", nullable = true)] pub runtime_version_constraint: Option<RuntimeVersionConstraintPatch>,
pub runtime_version_constraint: Option<Option<String>>,
/// Parameter schema (StackStorm-style with inline required/secret) /// Parameter schema (StackStorm-style with inline required/secret)
#[schema(value_type = Object, nullable = true)] #[schema(value_type = Object, nullable = true)]
@@ -89,6 +88,14 @@ pub struct UpdateActionRequest {
pub out_schema: Option<JsonValue>, pub out_schema: Option<JsonValue>,
} }
/// Explicit patch operation for a nullable runtime version constraint.
#[derive(Debug, Clone, Deserialize, Serialize, ToSchema)]
#[serde(tag = "op", content = "value", rename_all = "snake_case")]
pub enum RuntimeVersionConstraintPatch {
Set(String),
Clear,
}
/// Response DTO for action information /// Response DTO for action information
#[derive(Debug, Clone, Serialize, ToSchema)] #[derive(Debug, Clone, Serialize, ToSchema)]
pub struct ActionResponse { pub struct ActionResponse {

View File

@@ -97,19 +97,41 @@ pub struct UpdateArtifactRequest {
pub retention_limit: Option<i32>, pub retention_limit: Option<i32>,
/// Updated name /// Updated name
pub name: Option<String>, pub name: Option<ArtifactStringPatch>,
/// Updated description /// Updated description
pub description: Option<String>, pub description: Option<ArtifactStringPatch>,
/// Updated content type /// Updated content type
pub content_type: Option<String>, pub content_type: Option<ArtifactStringPatch>,
/// Updated execution ID (re-links artifact to a different execution) /// Updated execution patch (set a new execution ID or clear the link)
pub execution: Option<i64>, pub execution: Option<ArtifactExecutionPatch>,
/// Updated structured data (replaces existing data entirely) /// Updated structured data (replaces existing data entirely)
pub data: Option<JsonValue>, pub data: Option<ArtifactJsonPatch>,
}
/// Explicit patch operation for a nullable execution link.
#[derive(Debug, Clone, Deserialize, Serialize, ToSchema)]
#[serde(tag = "op", content = "value", rename_all = "snake_case")]
pub enum ArtifactExecutionPatch {
Set(i64),
Clear,
}
#[derive(Debug, Clone, Deserialize, Serialize, ToSchema)]
#[serde(tag = "op", content = "value", rename_all = "snake_case")]
pub enum ArtifactStringPatch {
Set(String),
Clear,
}
#[derive(Debug, Clone, Deserialize, Serialize, ToSchema)]
#[serde(tag = "op", content = "value", rename_all = "snake_case")]
pub enum ArtifactJsonPatch {
Set(JsonValue),
Clear,
} }
/// Request DTO for appending to a progress-type artifact /// Request DTO for appending to a progress-type artifact

View File

@@ -13,6 +13,7 @@ pub mod key;
pub mod pack; pub mod pack;
pub mod permission; pub mod permission;
pub mod rule; pub mod rule;
pub mod runtime;
pub mod trigger; pub mod trigger;
pub mod webhook; pub mod webhook;
pub mod workflow; pub mod workflow;
@@ -55,6 +56,7 @@ pub use permission::{
UpdateIdentityRequest, UpdateIdentityRequest,
}; };
pub use rule::{CreateRuleRequest, RuleResponse, RuleSummary, UpdateRuleRequest}; pub use rule::{CreateRuleRequest, RuleResponse, RuleSummary, UpdateRuleRequest};
pub use runtime::{CreateRuntimeRequest, RuntimeResponse, RuntimeSummary, UpdateRuntimeRequest};
pub use trigger::{ pub use trigger::{
CreateSensorRequest, CreateTriggerRequest, SensorResponse, SensorSummary, TriggerResponse, CreateSensorRequest, CreateTriggerRequest, SensorResponse, SensorSummary, TriggerResponse,
TriggerSummary, UpdateSensorRequest, UpdateTriggerRequest, TriggerSummary, UpdateSensorRequest, UpdateTriggerRequest,

View File

@@ -129,7 +129,7 @@ pub struct UpdatePackRequest {
/// Pack description /// Pack description
#[schema(example = "Enhanced Slack integration with new features")] #[schema(example = "Enhanced Slack integration with new features")]
pub description: Option<String>, pub description: Option<PackDescriptionPatch>,
/// Pack version /// Pack version
#[validate(length(min = 1, max = 50))] #[validate(length(min = 1, max = 50))]
@@ -165,6 +165,13 @@ pub struct UpdatePackRequest {
pub is_standard: Option<bool>, pub is_standard: Option<bool>,
} }
#[derive(Debug, Clone, Deserialize, Serialize, ToSchema)]
#[serde(tag = "op", content = "value", rename_all = "snake_case")]
pub enum PackDescriptionPatch {
Set(String),
Clear,
}
/// Response DTO for pack information /// Response DTO for pack information
#[derive(Debug, Clone, Serialize, ToSchema)] #[derive(Debug, Clone, Serialize, ToSchema)]
pub struct PackResponse { pub struct PackResponse {

View File

@@ -0,0 +1,181 @@
//! Runtime DTOs for API requests and responses
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use serde_json::Value as JsonValue;
use utoipa::ToSchema;
use validator::Validate;
/// Request DTO for creating a runtime.
#[derive(Debug, Clone, Deserialize, Validate, ToSchema)]
pub struct CreateRuntimeRequest {
/// Unique reference identifier (e.g. "core.python", "core.nodejs")
#[validate(length(min = 1, max = 255))]
#[schema(example = "core.python")]
pub r#ref: String,
/// Optional pack reference this runtime belongs to
#[validate(length(min = 1, max = 255))]
#[schema(example = "core", nullable = true)]
pub pack_ref: Option<String>,
/// Optional human-readable description
#[validate(length(min = 1))]
#[schema(example = "Python runtime with virtualenv support", nullable = true)]
pub description: Option<String>,
/// Display name
#[validate(length(min = 1, max = 255))]
#[schema(example = "Python")]
pub name: String,
/// Distribution metadata used for verification and platform support
#[serde(default)]
#[schema(value_type = Object, example = json!({"linux": {"supported": true}}))]
pub distributions: JsonValue,
/// Optional installation metadata
#[serde(skip_serializing_if = "Option::is_none")]
#[schema(value_type = Object, nullable = true, example = json!({"method": "system"}))]
pub installation: Option<JsonValue>,
/// Runtime execution configuration
#[serde(default)]
#[schema(value_type = Object, example = json!({"interpreter": {"command": "python3"}}))]
pub execution_config: JsonValue,
}
/// Request DTO for updating a runtime.
#[derive(Debug, Clone, Deserialize, Validate, ToSchema)]
pub struct UpdateRuntimeRequest {
/// Optional human-readable description patch.
pub description: Option<NullableStringPatch>,
/// Display name
#[validate(length(min = 1, max = 255))]
#[schema(example = "Python 3")]
pub name: Option<String>,
/// Distribution metadata used for verification and platform support
#[schema(value_type = Object, nullable = true)]
pub distributions: Option<JsonValue>,
/// Optional installation metadata patch.
pub installation: Option<NullableJsonPatch>,
/// Runtime execution configuration
#[schema(value_type = Object, nullable = true)]
pub execution_config: Option<JsonValue>,
}
/// Explicit patch operation for nullable string fields.
#[derive(Debug, Clone, Deserialize, Serialize, ToSchema)]
#[serde(tag = "op", content = "value", rename_all = "snake_case")]
pub enum NullableStringPatch {
#[schema(title = "SetString")]
Set(String),
Clear,
}
/// Explicit patch operation for nullable JSON fields.
#[derive(Debug, Clone, Deserialize, Serialize, ToSchema)]
#[serde(tag = "op", content = "value", rename_all = "snake_case")]
pub enum NullableJsonPatch {
#[schema(title = "SetJson")]
Set(JsonValue),
Clear,
}
/// Full runtime response.
#[derive(Debug, Clone, Serialize, ToSchema)]
pub struct RuntimeResponse {
#[schema(example = 1)]
pub id: i64,
#[schema(example = "core.python")]
pub r#ref: String,
#[schema(example = 1, nullable = true)]
pub pack: Option<i64>,
#[schema(example = "core", nullable = true)]
pub pack_ref: Option<String>,
#[schema(example = "Python runtime with virtualenv support", nullable = true)]
pub description: Option<String>,
#[schema(example = "Python")]
pub name: String,
#[schema(value_type = Object)]
pub distributions: JsonValue,
#[schema(value_type = Object, nullable = true)]
pub installation: Option<JsonValue>,
#[schema(value_type = Object)]
pub execution_config: JsonValue,
#[schema(example = "2024-01-13T10:30:00Z")]
pub created: DateTime<Utc>,
#[schema(example = "2024-01-13T10:30:00Z")]
pub updated: DateTime<Utc>,
}
/// Runtime summary for list views.
#[derive(Debug, Clone, Serialize, ToSchema)]
pub struct RuntimeSummary {
#[schema(example = 1)]
pub id: i64,
#[schema(example = "core.python")]
pub r#ref: String,
#[schema(example = "core", nullable = true)]
pub pack_ref: Option<String>,
#[schema(example = "Python runtime with virtualenv support", nullable = true)]
pub description: Option<String>,
#[schema(example = "Python")]
pub name: String,
#[schema(example = "2024-01-13T10:30:00Z")]
pub created: DateTime<Utc>,
#[schema(example = "2024-01-13T10:30:00Z")]
pub updated: DateTime<Utc>,
}
impl From<attune_common::models::runtime::Runtime> for RuntimeResponse {
fn from(runtime: attune_common::models::runtime::Runtime) -> Self {
Self {
id: runtime.id,
r#ref: runtime.r#ref,
pack: runtime.pack,
pack_ref: runtime.pack_ref,
description: runtime.description,
name: runtime.name,
distributions: runtime.distributions,
installation: runtime.installation,
execution_config: runtime.execution_config,
created: runtime.created,
updated: runtime.updated,
}
}
}
impl From<attune_common::models::runtime::Runtime> for RuntimeSummary {
fn from(runtime: attune_common::models::runtime::Runtime) -> Self {
Self {
id: runtime.id,
r#ref: runtime.r#ref,
pack_ref: runtime.pack_ref,
description: runtime.description,
name: runtime.name,
created: runtime.created,
updated: runtime.updated,
}
}
}

View File

@@ -54,21 +54,35 @@ pub struct UpdateTriggerRequest {
/// Trigger description /// Trigger description
#[schema(example = "Updated webhook trigger description")] #[schema(example = "Updated webhook trigger description")]
pub description: Option<String>, pub description: Option<TriggerStringPatch>,
/// Parameter schema (StackStorm-style with inline required/secret) /// Parameter schema (StackStorm-style with inline required/secret)
#[schema(value_type = Object, nullable = true)] #[schema(value_type = Object, nullable = true)]
pub param_schema: Option<JsonValue>, pub param_schema: Option<TriggerJsonPatch>,
/// Output schema /// Output schema
#[schema(value_type = Object, nullable = true)] #[schema(value_type = Object, nullable = true)]
pub out_schema: Option<JsonValue>, pub out_schema: Option<TriggerJsonPatch>,
/// Whether the trigger is enabled /// Whether the trigger is enabled
#[schema(example = true)] #[schema(example = true)]
pub enabled: Option<bool>, pub enabled: Option<bool>,
} }
#[derive(Debug, Clone, Deserialize, Serialize, ToSchema)]
#[serde(tag = "op", content = "value", rename_all = "snake_case")]
pub enum TriggerStringPatch {
Set(String),
Clear,
}
#[derive(Debug, Clone, Deserialize, Serialize, ToSchema)]
#[serde(tag = "op", content = "value", rename_all = "snake_case")]
pub enum TriggerJsonPatch {
Set(JsonValue),
Clear,
}
/// Response DTO for trigger information /// Response DTO for trigger information
#[derive(Debug, Clone, Serialize, ToSchema)] #[derive(Debug, Clone, Serialize, ToSchema)]
pub struct TriggerResponse { pub struct TriggerResponse {
@@ -244,13 +258,20 @@ pub struct UpdateSensorRequest {
/// Parameter schema (StackStorm-style with inline required/secret) /// Parameter schema (StackStorm-style with inline required/secret)
#[schema(value_type = Object, nullable = true)] #[schema(value_type = Object, nullable = true)]
pub param_schema: Option<JsonValue>, pub param_schema: Option<SensorJsonPatch>,
/// Whether the sensor is enabled /// Whether the sensor is enabled
#[schema(example = false)] #[schema(example = false)]
pub enabled: Option<bool>, pub enabled: Option<bool>,
} }
#[derive(Debug, Clone, Deserialize, Serialize, ToSchema)]
#[serde(tag = "op", content = "value", rename_all = "snake_case")]
pub enum SensorJsonPatch {
Set(JsonValue),
Clear,
}
/// Response DTO for sensor information /// Response DTO for sensor information
#[derive(Debug, Clone, Serialize, ToSchema)] #[derive(Debug, Clone, Serialize, ToSchema)]
pub struct SensorResponse { pub struct SensorResponse {

View File

@@ -31,6 +31,7 @@ use crate::dto::{
IdentitySummary, PermissionAssignmentResponse, PermissionSetSummary, UpdateIdentityRequest, IdentitySummary, PermissionAssignmentResponse, PermissionSetSummary, UpdateIdentityRequest,
}, },
rule::{CreateRuleRequest, RuleResponse, RuleSummary, UpdateRuleRequest}, rule::{CreateRuleRequest, RuleResponse, RuleSummary, UpdateRuleRequest},
runtime::{CreateRuntimeRequest, RuntimeResponse, RuntimeSummary, UpdateRuntimeRequest},
trigger::{ trigger::{
CreateSensorRequest, CreateTriggerRequest, SensorResponse, SensorSummary, TriggerResponse, CreateSensorRequest, CreateTriggerRequest, SensorResponse, SensorSummary, TriggerResponse,
TriggerSummary, UpdateSensorRequest, UpdateTriggerRequest, TriggerSummary, UpdateSensorRequest, UpdateTriggerRequest,
@@ -96,6 +97,14 @@ use crate::dto::{
crate::routes::actions::delete_action, crate::routes::actions::delete_action,
crate::routes::actions::get_queue_stats, crate::routes::actions::get_queue_stats,
// Runtimes
crate::routes::runtimes::list_runtimes,
crate::routes::runtimes::list_runtimes_by_pack,
crate::routes::runtimes::get_runtime,
crate::routes::runtimes::create_runtime,
crate::routes::runtimes::update_runtime,
crate::routes::runtimes::delete_runtime,
// Triggers // Triggers
crate::routes::triggers::list_triggers, crate::routes::triggers::list_triggers,
crate::routes::triggers::list_enabled_triggers, crate::routes::triggers::list_enabled_triggers,
@@ -197,6 +206,7 @@ use crate::dto::{
ApiResponse<PackResponse>, ApiResponse<PackResponse>,
ApiResponse<PackInstallResponse>, ApiResponse<PackInstallResponse>,
ApiResponse<ActionResponse>, ApiResponse<ActionResponse>,
ApiResponse<RuntimeResponse>,
ApiResponse<TriggerResponse>, ApiResponse<TriggerResponse>,
ApiResponse<SensorResponse>, ApiResponse<SensorResponse>,
ApiResponse<RuleResponse>, ApiResponse<RuleResponse>,
@@ -211,6 +221,7 @@ use crate::dto::{
ApiResponse<QueueStatsResponse>, ApiResponse<QueueStatsResponse>,
PaginatedResponse<PackSummary>, PaginatedResponse<PackSummary>,
PaginatedResponse<ActionSummary>, PaginatedResponse<ActionSummary>,
PaginatedResponse<RuntimeSummary>,
PaginatedResponse<TriggerSummary>, PaginatedResponse<TriggerSummary>,
PaginatedResponse<SensorSummary>, PaginatedResponse<SensorSummary>,
PaginatedResponse<RuleSummary>, PaginatedResponse<RuleSummary>,
@@ -258,6 +269,12 @@ use crate::dto::{
PermissionSetSummary, PermissionSetSummary,
PermissionAssignmentResponse, PermissionAssignmentResponse,
CreatePermissionAssignmentRequest, CreatePermissionAssignmentRequest,
// Runtime DTOs
CreateRuntimeRequest,
UpdateRuntimeRequest,
RuntimeResponse,
RuntimeSummary,
IdentitySummary, IdentitySummary,
// Action DTOs // Action DTOs

View File

@@ -15,7 +15,7 @@ use attune_common::repositories::{
action::{ActionRepository, ActionSearchFilters, CreateActionInput, UpdateActionInput}, action::{ActionRepository, ActionSearchFilters, CreateActionInput, UpdateActionInput},
pack::PackRepository, pack::PackRepository,
queue_stats::QueueStatsRepository, queue_stats::QueueStatsRepository,
Create, Delete, FindByRef, Update, Create, Delete, FindByRef, Patch, Update,
}; };
use crate::{ use crate::{
@@ -24,7 +24,7 @@ use crate::{
dto::{ dto::{
action::{ action::{
ActionResponse, ActionSummary, CreateActionRequest, QueueStatsResponse, ActionResponse, ActionSummary, CreateActionRequest, QueueStatsResponse,
UpdateActionRequest, RuntimeVersionConstraintPatch, UpdateActionRequest,
}, },
common::{PaginatedResponse, PaginationParams}, common::{PaginatedResponse, PaginationParams},
ApiResponse, SuccessResponse, ApiResponse, SuccessResponse,
@@ -280,7 +280,10 @@ pub async fn update_action(
description: request.description, description: request.description,
entrypoint: request.entrypoint, entrypoint: request.entrypoint,
runtime: request.runtime, runtime: request.runtime,
runtime_version_constraint: request.runtime_version_constraint, runtime_version_constraint: request.runtime_version_constraint.map(|patch| match patch {
RuntimeVersionConstraintPatch::Set(value) => Patch::Set(value),
RuntimeVersionConstraintPatch::Clear => Patch::Clear,
}),
param_schema: request.param_schema, param_schema: request.param_schema,
out_schema: request.out_schema, out_schema: request.out_schema,
parameter_delivery: None, parameter_delivery: None,

View File

@@ -36,15 +36,16 @@ use attune_common::repositories::{
ArtifactRepository, ArtifactSearchFilters, ArtifactVersionRepository, CreateArtifactInput, ArtifactRepository, ArtifactSearchFilters, ArtifactVersionRepository, CreateArtifactInput,
CreateArtifactVersionInput, UpdateArtifactInput, CreateArtifactVersionInput, UpdateArtifactInput,
}, },
Create, Delete, FindById, FindByRef, Update, Create, Delete, FindById, FindByRef, Patch, Update,
}; };
use crate::{ use crate::{
auth::middleware::RequireAuth, auth::middleware::RequireAuth,
dto::{ dto::{
artifact::{ artifact::{
AllocateFileVersionByRefRequest, AppendProgressRequest, ArtifactQueryParams, AllocateFileVersionByRefRequest, AppendProgressRequest, ArtifactExecutionPatch,
ArtifactResponse, ArtifactSummary, ArtifactVersionResponse, ArtifactVersionSummary, ArtifactJsonPatch, ArtifactQueryParams, ArtifactResponse, ArtifactStringPatch,
ArtifactSummary, ArtifactVersionResponse, ArtifactVersionSummary,
CreateArtifactRequest, CreateFileVersionRequest, CreateVersionJsonRequest, CreateArtifactRequest, CreateFileVersionRequest, CreateVersionJsonRequest,
SetDataRequest, UpdateArtifactRequest, SetDataRequest, UpdateArtifactRequest,
}, },
@@ -257,12 +258,27 @@ pub async fn update_artifact(
visibility: request.visibility, visibility: request.visibility,
retention_policy: request.retention_policy, retention_policy: request.retention_policy,
retention_limit: request.retention_limit, retention_limit: request.retention_limit,
name: request.name, name: request.name.map(|patch| match patch {
description: request.description, ArtifactStringPatch::Set(value) => Patch::Set(value),
content_type: request.content_type, ArtifactStringPatch::Clear => Patch::Clear,
}),
description: request.description.map(|patch| match patch {
ArtifactStringPatch::Set(value) => Patch::Set(value),
ArtifactStringPatch::Clear => Patch::Clear,
}),
content_type: request.content_type.map(|patch| match patch {
ArtifactStringPatch::Set(value) => Patch::Set(value),
ArtifactStringPatch::Clear => Patch::Clear,
}),
size_bytes: None, // Managed by version creation trigger size_bytes: None, // Managed by version creation trigger
execution: request.execution.map(Some), execution: request.execution.map(|patch| match patch {
data: request.data, ArtifactExecutionPatch::Set(value) => Patch::Set(value),
ArtifactExecutionPatch::Clear => Patch::Clear,
}),
data: request.data.map(|patch| match patch {
ArtifactJsonPatch::Set(value) => Patch::Set(value),
ArtifactJsonPatch::Clear => Patch::Clear,
}),
}; };
let updated = ArtifactRepository::update(&state.db, id, input).await?; let updated = ArtifactRepository::update(&state.db, id, input).await?;
@@ -1155,7 +1171,7 @@ pub async fn upload_version_by_ref(
description: None, description: None,
content_type: None, content_type: None,
size_bytes: None, size_bytes: None,
execution: execution_id.map(Some), execution: execution_id.map(Patch::Set),
data: None, data: None,
}; };
ArtifactRepository::update(&state.db, existing.id, update_input).await? ArtifactRepository::update(&state.db, existing.id, update_input).await?
@@ -1303,7 +1319,7 @@ pub async fn allocate_file_version_by_ref(
description: None, description: None,
content_type: None, content_type: None,
size_bytes: None, size_bytes: None,
execution: request.execution.map(Some), execution: request.execution.map(Patch::Set),
data: None, data: None,
}; };
ArtifactRepository::update(&state.db, existing.id, update_input).await? ArtifactRepository::update(&state.db, existing.id, update_input).await?

View File

@@ -13,6 +13,7 @@ pub mod keys;
pub mod packs; pub mod packs;
pub mod permissions; pub mod permissions;
pub mod rules; pub mod rules;
pub mod runtimes;
pub mod triggers; pub mod triggers;
pub mod webhooks; pub mod webhooks;
pub mod workflows; pub mod workflows;
@@ -30,6 +31,7 @@ pub use keys::routes as key_routes;
pub use packs::routes as pack_routes; pub use packs::routes as pack_routes;
pub use permissions::routes as permission_routes; pub use permissions::routes as permission_routes;
pub use rules::routes as rule_routes; pub use rules::routes as rule_routes;
pub use runtimes::routes as runtime_routes;
pub use triggers::routes as trigger_routes; pub use triggers::routes as trigger_routes;
pub use webhooks::routes as webhook_routes; pub use webhooks::routes as webhook_routes;
pub use workflows::routes as workflow_routes; pub use workflows::routes as workflow_routes;

View File

@@ -16,7 +16,8 @@ use attune_common::mq::{MessageEnvelope, MessageType, PackRegisteredPayload};
use attune_common::rbac::{Action, AuthorizationContext, Resource}; use attune_common::rbac::{Action, AuthorizationContext, Resource};
use attune_common::repositories::{ use attune_common::repositories::{
pack::{CreatePackInput, UpdatePackInput}, pack::{CreatePackInput, UpdatePackInput},
Create, Delete, FindById, FindByRef, PackRepository, PackTestRepository, Pagination, Update, Create, Delete, FindById, FindByRef, PackRepository, PackTestRepository, Pagination, Patch,
Update,
}; };
use attune_common::workflow::{PackWorkflowService, PackWorkflowServiceConfig}; use attune_common::workflow::{PackWorkflowService, PackWorkflowServiceConfig};
@@ -29,8 +30,9 @@ use crate::{
BuildPackEnvsRequest, BuildPackEnvsResponse, CreatePackRequest, DownloadPacksRequest, BuildPackEnvsRequest, BuildPackEnvsResponse, CreatePackRequest, DownloadPacksRequest,
DownloadPacksResponse, GetPackDependenciesRequest, GetPackDependenciesResponse, DownloadPacksResponse, GetPackDependenciesRequest, GetPackDependenciesResponse,
InstallPackRequest, PackInstallResponse, PackResponse, PackSummary, InstallPackRequest, PackInstallResponse, PackResponse, PackSummary,
PackWorkflowSyncResponse, PackWorkflowValidationResponse, RegisterPackRequest, PackDescriptionPatch, PackWorkflowSyncResponse, PackWorkflowValidationResponse,
RegisterPacksRequest, RegisterPacksResponse, UpdatePackRequest, WorkflowSyncResult, RegisterPackRequest, RegisterPacksRequest, RegisterPacksResponse, UpdatePackRequest,
WorkflowSyncResult,
}, },
ApiResponse, SuccessResponse, ApiResponse, SuccessResponse,
}, },
@@ -258,7 +260,10 @@ pub async fn update_pack(
// Create update input // Create update input
let update_input = UpdatePackInput { let update_input = UpdatePackInput {
label: request.label, label: request.label,
description: request.description, description: request.description.map(|patch| match patch {
PackDescriptionPatch::Set(value) => Patch::Set(value),
PackDescriptionPatch::Clear => Patch::Clear,
}),
version: request.version, version: request.version,
conf_schema: request.conf_schema, conf_schema: request.conf_schema,
config: request.config, config: request.config,
@@ -876,7 +881,10 @@ async fn register_pack_internal(
// Update existing pack in place — preserves pack ID and all child entity IDs // Update existing pack in place — preserves pack ID and all child entity IDs
let update_input = UpdatePackInput { let update_input = UpdatePackInput {
label: Some(label), label: Some(label),
description: Some(description.unwrap_or_default()), description: Some(match description {
Some(value) => Patch::Set(value),
None => Patch::Clear,
}),
version: Some(version.clone()), version: Some(version.clone()),
conf_schema: Some(conf_schema), conf_schema: Some(conf_schema),
config: None, // preserve user-set config config: None, // preserve user-set config

View File

@@ -0,0 +1,303 @@
//! Runtime management API routes
use axum::{
extract::{Path, Query, State},
http::StatusCode,
response::IntoResponse,
routing::get,
Json, Router,
};
use std::sync::Arc;
use validator::Validate;
use attune_common::repositories::{
pack::PackRepository,
runtime::{CreateRuntimeInput, RuntimeRepository, UpdateRuntimeInput},
Create, Delete, FindByRef, List, Patch, Update,
};
use crate::{
auth::middleware::RequireAuth,
dto::{
common::{PaginatedResponse, PaginationParams},
runtime::{
CreateRuntimeRequest, NullableJsonPatch, NullableStringPatch, RuntimeResponse,
RuntimeSummary, UpdateRuntimeRequest,
},
ApiResponse, SuccessResponse,
},
middleware::{ApiError, ApiResult},
state::AppState,
};
#[utoipa::path(
get,
path = "/api/v1/runtimes",
tag = "runtimes",
params(PaginationParams),
responses(
(status = 200, description = "List of runtimes", body = PaginatedResponse<RuntimeSummary>)
),
security(("bearer_auth" = []))
)]
pub async fn list_runtimes(
State(state): State<Arc<AppState>>,
RequireAuth(_user): RequireAuth,
Query(pagination): Query<PaginationParams>,
) -> ApiResult<impl IntoResponse> {
let all_runtimes = RuntimeRepository::list(&state.db).await?;
let total = all_runtimes.len() as u64;
let rows: Vec<_> = all_runtimes
.into_iter()
.skip(pagination.offset() as usize)
.take(pagination.limit() as usize)
.collect();
let response = PaginatedResponse::new(
rows.into_iter().map(RuntimeSummary::from).collect(),
&pagination,
total,
);
Ok((StatusCode::OK, Json(response)))
}
#[utoipa::path(
get,
path = "/api/v1/packs/{pack_ref}/runtimes",
tag = "runtimes",
params(
("pack_ref" = String, Path, description = "Pack reference identifier"),
PaginationParams
),
responses(
(status = 200, description = "List of runtimes for a pack", body = PaginatedResponse<RuntimeSummary>),
(status = 404, description = "Pack not found")
),
security(("bearer_auth" = []))
)]
pub async fn list_runtimes_by_pack(
State(state): State<Arc<AppState>>,
RequireAuth(_user): RequireAuth,
Path(pack_ref): Path<String>,
Query(pagination): Query<PaginationParams>,
) -> ApiResult<impl IntoResponse> {
let pack = PackRepository::find_by_ref(&state.db, &pack_ref)
.await?
.ok_or_else(|| ApiError::NotFound(format!("Pack '{}' not found", pack_ref)))?;
let all_runtimes = RuntimeRepository::find_by_pack(&state.db, pack.id).await?;
let total = all_runtimes.len() as u64;
let rows: Vec<_> = all_runtimes
.into_iter()
.skip(pagination.offset() as usize)
.take(pagination.limit() as usize)
.collect();
let response = PaginatedResponse::new(
rows.into_iter().map(RuntimeSummary::from).collect(),
&pagination,
total,
);
Ok((StatusCode::OK, Json(response)))
}
#[utoipa::path(
get,
path = "/api/v1/runtimes/{ref}",
tag = "runtimes",
params(("ref" = String, Path, description = "Runtime reference identifier")),
responses(
(status = 200, description = "Runtime details", body = ApiResponse<RuntimeResponse>),
(status = 404, description = "Runtime not found")
),
security(("bearer_auth" = []))
)]
pub async fn get_runtime(
State(state): State<Arc<AppState>>,
RequireAuth(_user): RequireAuth,
Path(runtime_ref): Path<String>,
) -> ApiResult<impl IntoResponse> {
let runtime = RuntimeRepository::find_by_ref(&state.db, &runtime_ref)
.await?
.ok_or_else(|| ApiError::NotFound(format!("Runtime '{}' not found", runtime_ref)))?;
Ok((
StatusCode::OK,
Json(ApiResponse::new(RuntimeResponse::from(runtime))),
))
}
#[utoipa::path(
post,
path = "/api/v1/runtimes",
tag = "runtimes",
request_body = CreateRuntimeRequest,
responses(
(status = 201, description = "Runtime created successfully", body = ApiResponse<RuntimeResponse>),
(status = 400, description = "Validation error"),
(status = 404, description = "Pack not found"),
(status = 409, description = "Runtime with same ref already exists")
),
security(("bearer_auth" = []))
)]
pub async fn create_runtime(
State(state): State<Arc<AppState>>,
RequireAuth(_user): RequireAuth,
Json(request): Json<CreateRuntimeRequest>,
) -> ApiResult<impl IntoResponse> {
request.validate()?;
if RuntimeRepository::find_by_ref(&state.db, &request.r#ref)
.await?
.is_some()
{
return Err(ApiError::Conflict(format!(
"Runtime with ref '{}' already exists",
request.r#ref
)));
}
let (pack_id, pack_ref) = if let Some(ref pack_ref_str) = request.pack_ref {
let pack = PackRepository::find_by_ref(&state.db, pack_ref_str)
.await?
.ok_or_else(|| ApiError::NotFound(format!("Pack '{}' not found", pack_ref_str)))?;
(Some(pack.id), Some(pack.r#ref))
} else {
(None, None)
};
let runtime = RuntimeRepository::create(
&state.db,
CreateRuntimeInput {
r#ref: request.r#ref,
pack: pack_id,
pack_ref,
description: request.description,
name: request.name,
distributions: request.distributions,
installation: request.installation,
execution_config: request.execution_config,
},
)
.await?;
Ok((
StatusCode::CREATED,
Json(ApiResponse::with_message(
RuntimeResponse::from(runtime),
"Runtime created successfully",
)),
))
}
#[utoipa::path(
put,
path = "/api/v1/runtimes/{ref}",
tag = "runtimes",
params(("ref" = String, Path, description = "Runtime reference identifier")),
request_body = UpdateRuntimeRequest,
responses(
(status = 200, description = "Runtime updated successfully", body = ApiResponse<RuntimeResponse>),
(status = 400, description = "Validation error"),
(status = 404, description = "Runtime not found")
),
security(("bearer_auth" = []))
)]
pub async fn update_runtime(
State(state): State<Arc<AppState>>,
RequireAuth(_user): RequireAuth,
Path(runtime_ref): Path<String>,
Json(request): Json<UpdateRuntimeRequest>,
) -> ApiResult<impl IntoResponse> {
request.validate()?;
let existing_runtime = RuntimeRepository::find_by_ref(&state.db, &runtime_ref)
.await?
.ok_or_else(|| ApiError::NotFound(format!("Runtime '{}' not found", runtime_ref)))?;
let runtime = RuntimeRepository::update(
&state.db,
existing_runtime.id,
UpdateRuntimeInput {
description: request.description.map(|patch| match patch {
NullableStringPatch::Set(value) => Patch::Set(value),
NullableStringPatch::Clear => Patch::Clear,
}),
name: request.name,
distributions: request.distributions,
installation: request.installation.map(|patch| match patch {
NullableJsonPatch::Set(value) => Patch::Set(value),
NullableJsonPatch::Clear => Patch::Clear,
}),
execution_config: request.execution_config,
},
)
.await?;
Ok((
StatusCode::OK,
Json(ApiResponse::with_message(
RuntimeResponse::from(runtime),
"Runtime updated successfully",
)),
))
}
#[utoipa::path(
delete,
path = "/api/v1/runtimes/{ref}",
tag = "runtimes",
params(("ref" = String, Path, description = "Runtime reference identifier")),
responses(
(status = 200, description = "Runtime deleted successfully", body = SuccessResponse),
(status = 404, description = "Runtime not found")
),
security(("bearer_auth" = []))
)]
pub async fn delete_runtime(
State(state): State<Arc<AppState>>,
RequireAuth(_user): RequireAuth,
Path(runtime_ref): Path<String>,
) -> ApiResult<impl IntoResponse> {
let runtime = RuntimeRepository::find_by_ref(&state.db, &runtime_ref)
.await?
.ok_or_else(|| ApiError::NotFound(format!("Runtime '{}' not found", runtime_ref)))?;
let deleted = RuntimeRepository::delete(&state.db, runtime.id).await?;
if !deleted {
return Err(ApiError::NotFound(format!(
"Runtime '{}' not found",
runtime_ref
)));
}
Ok((
StatusCode::OK,
Json(SuccessResponse::new(format!(
"Runtime '{}' deleted successfully",
runtime_ref
))),
))
}
pub fn routes() -> Router<Arc<AppState>> {
Router::new()
.route("/runtimes", get(list_runtimes).post(create_runtime))
.route(
"/runtimes/{ref}",
get(get_runtime).put(update_runtime).delete(delete_runtime),
)
.route("/packs/{pack_ref}/runtimes", get(list_runtimes_by_pack))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_runtime_routes_structure() {
let _router = routes();
}
}

View File

@@ -17,7 +17,7 @@ use attune_common::repositories::{
CreateSensorInput, CreateTriggerInput, SensorRepository, SensorSearchFilters, CreateSensorInput, CreateTriggerInput, SensorRepository, SensorSearchFilters,
TriggerRepository, TriggerSearchFilters, UpdateSensorInput, UpdateTriggerInput, TriggerRepository, TriggerSearchFilters, UpdateSensorInput, UpdateTriggerInput,
}, },
Create, Delete, FindByRef, Update, Create, Delete, FindByRef, Patch, Update,
}; };
use crate::{ use crate::{
@@ -25,8 +25,9 @@ use crate::{
dto::{ dto::{
common::{PaginatedResponse, PaginationParams}, common::{PaginatedResponse, PaginationParams},
trigger::{ trigger::{
CreateSensorRequest, CreateTriggerRequest, SensorResponse, SensorSummary, CreateSensorRequest, CreateTriggerRequest, SensorJsonPatch, SensorResponse,
TriggerResponse, TriggerSummary, UpdateSensorRequest, UpdateTriggerRequest, SensorSummary, TriggerJsonPatch, TriggerResponse, TriggerStringPatch,
TriggerSummary, UpdateSensorRequest, UpdateTriggerRequest,
}, },
ApiResponse, SuccessResponse, ApiResponse, SuccessResponse,
}, },
@@ -274,10 +275,19 @@ pub async fn update_trigger(
// Create update input // Create update input
let update_input = UpdateTriggerInput { let update_input = UpdateTriggerInput {
label: request.label, label: request.label,
description: request.description, description: request.description.map(|patch| match patch {
TriggerStringPatch::Set(value) => Patch::Set(value),
TriggerStringPatch::Clear => Patch::Clear,
}),
enabled: request.enabled, enabled: request.enabled,
param_schema: request.param_schema, param_schema: request.param_schema.map(|patch| match patch {
out_schema: request.out_schema, TriggerJsonPatch::Set(value) => Patch::Set(value),
TriggerJsonPatch::Clear => Patch::Clear,
}),
out_schema: request.out_schema.map(|patch| match patch {
TriggerJsonPatch::Set(value) => Patch::Set(value),
TriggerJsonPatch::Clear => Patch::Clear,
}),
}; };
let trigger = TriggerRepository::update(&state.db, existing_trigger.id, update_input).await?; let trigger = TriggerRepository::update(&state.db, existing_trigger.id, update_input).await?;
@@ -722,7 +732,10 @@ pub async fn update_sensor(
trigger: None, trigger: None,
trigger_ref: None, trigger_ref: None,
enabled: request.enabled, enabled: request.enabled,
param_schema: request.param_schema, param_schema: request.param_schema.map(|patch| match patch {
SensorJsonPatch::Set(value) => Patch::Set(value),
SensorJsonPatch::Clear => Patch::Clear,
}),
config: None, config: None,
}; };

View File

@@ -47,6 +47,7 @@ impl Server {
let api_v1 = Router::new() let api_v1 = Router::new()
.merge(routes::pack_routes()) .merge(routes::pack_routes())
.merge(routes::action_routes()) .merge(routes::action_routes())
.merge(routes::runtime_routes())
.merge(routes::rule_routes()) .merge(routes::rule_routes())
.merge(routes::execution_routes()) .merge(routes::execution_routes())
.merge(routes::trigger_routes()) .merge(routes::trigger_routes())

View File

@@ -1775,19 +1775,26 @@ async fn handle_update(
anyhow::bail!("At least one field must be provided to update"); anyhow::bail!("At least one field must be provided to update");
} }
#[derive(Serialize)]
#[serde(tag = "op", content = "value", rename_all = "snake_case")]
enum PackDescriptionPatch {
Set(String),
Clear,
}
#[derive(Serialize)] #[derive(Serialize)]
struct UpdatePackRequest { struct UpdatePackRequest {
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
label: Option<String>, label: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
description: Option<String>, description: Option<PackDescriptionPatch>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
version: Option<String>, version: Option<String>,
} }
let request = UpdatePackRequest { let request = UpdatePackRequest {
label, label,
description, description: description.map(PackDescriptionPatch::Set),
version, version,
}; };

View File

@@ -254,19 +254,26 @@ async fn handle_update(
anyhow::bail!("At least one field must be provided to update"); anyhow::bail!("At least one field must be provided to update");
} }
#[derive(Serialize)]
#[serde(tag = "op", content = "value", rename_all = "snake_case")]
enum TriggerDescriptionPatch {
Set(String),
Clear,
}
#[derive(Serialize)] #[derive(Serialize)]
struct UpdateTriggerRequest { struct UpdateTriggerRequest {
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
label: Option<String>, label: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
description: Option<String>, description: Option<TriggerDescriptionPatch>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
enabled: Option<bool>, enabled: Option<bool>,
} }
let request = UpdateTriggerRequest { let request = UpdateTriggerRequest {
label, label,
description, description: description.map(TriggerDescriptionPatch::Set),
enabled, enabled,
}; };

View File

@@ -42,7 +42,6 @@ use crate::repositories::action::{ActionRepository, UpdateActionInput};
use crate::repositories::identity::{ use crate::repositories::identity::{
CreatePermissionSetInput, PermissionSetRepository, UpdatePermissionSetInput, CreatePermissionSetInput, PermissionSetRepository, UpdatePermissionSetInput,
}; };
use crate::repositories::runtime::{CreateRuntimeInput, RuntimeRepository, UpdateRuntimeInput};
use crate::repositories::runtime_version::{ use crate::repositories::runtime_version::{
CreateRuntimeVersionInput, RuntimeVersionRepository, UpdateRuntimeVersionInput, CreateRuntimeVersionInput, RuntimeVersionRepository, UpdateRuntimeVersionInput,
}; };
@@ -53,7 +52,10 @@ use crate::repositories::trigger::{
use crate::repositories::workflow::{ use crate::repositories::workflow::{
CreateWorkflowDefinitionInput, UpdateWorkflowDefinitionInput, WorkflowDefinitionRepository, CreateWorkflowDefinitionInput, UpdateWorkflowDefinitionInput, WorkflowDefinitionRepository,
}; };
use crate::repositories::{Create, Delete, FindById, FindByRef, Update}; use crate::repositories::{
runtime::{CreateRuntimeInput, RuntimeRepository, UpdateRuntimeInput},
Create, Delete, FindById, FindByRef, Patch, Update,
};
use crate::version_matching::extract_version_components; use crate::version_matching::extract_version_components;
use crate::workflow::parser::parse_workflow_yaml; use crate::workflow::parser::parse_workflow_yaml;
@@ -405,10 +407,16 @@ impl<'a> PackComponentLoader<'a> {
// Check if runtime already exists — update in place if so // Check if runtime already exists — update in place if so
if let Some(existing) = RuntimeRepository::find_by_ref(self.pool, &runtime_ref).await? { if let Some(existing) = RuntimeRepository::find_by_ref(self.pool, &runtime_ref).await? {
let update_input = UpdateRuntimeInput { let update_input = UpdateRuntimeInput {
description, description: Some(match description {
Some(description) => Patch::Set(description),
None => Patch::Clear,
}),
name: Some(name), name: Some(name),
distributions: Some(distributions), distributions: Some(distributions),
installation, installation: Some(match installation {
Some(installation) => Patch::Set(installation),
None => Patch::Clear,
}),
execution_config: Some(execution_config), execution_config: Some(execution_config),
}; };
@@ -547,9 +555,18 @@ impl<'a> PackComponentLoader<'a> {
{ {
let update_input = UpdateRuntimeVersionInput { let update_input = UpdateRuntimeVersionInput {
version: None, // version string doesn't change version: None, // version string doesn't change
version_major: Some(version_major), version_major: Some(match version_major {
version_minor: Some(version_minor), Some(value) => Patch::Set(value),
version_patch: Some(version_patch), None => Patch::Clear,
}),
version_minor: Some(match version_minor {
Some(value) => Patch::Set(value),
None => Patch::Clear,
}),
version_patch: Some(match version_patch {
Some(value) => Patch::Set(value),
None => Patch::Clear,
}),
execution_config: Some(execution_config), execution_config: Some(execution_config),
distributions: Some(distributions), distributions: Some(distributions),
is_default: Some(is_default), is_default: Some(is_default),
@@ -713,10 +730,16 @@ impl<'a> PackComponentLoader<'a> {
if let Some(existing) = TriggerRepository::find_by_ref(self.pool, &trigger_ref).await? { if let Some(existing) = TriggerRepository::find_by_ref(self.pool, &trigger_ref).await? {
let update_input = UpdateTriggerInput { let update_input = UpdateTriggerInput {
label: Some(label), label: Some(label),
description: Some(description), description: Some(Patch::Set(description)),
enabled: Some(enabled), enabled: Some(enabled),
param_schema, param_schema: Some(match param_schema {
out_schema, Some(value) => Patch::Set(value),
None => Patch::Clear,
}),
out_schema: Some(match out_schema {
Some(value) => Patch::Set(value),
None => Patch::Clear,
}),
}; };
match TriggerRepository::update(self.pool, existing.id, update_input).await { match TriggerRepository::update(self.pool, existing.id, update_input).await {
@@ -921,7 +944,10 @@ impl<'a> PackComponentLoader<'a> {
description: Some(description), description: Some(description),
entrypoint: Some(entrypoint), entrypoint: Some(entrypoint),
runtime: runtime_id, runtime: runtime_id,
runtime_version_constraint: Some(runtime_version_constraint), runtime_version_constraint: Some(match runtime_version_constraint {
Some(value) => Patch::Set(value),
None => Patch::Clear,
}),
param_schema, param_schema,
out_schema, out_schema,
parameter_delivery: Some(parameter_delivery), parameter_delivery: Some(parameter_delivery),
@@ -1310,11 +1336,17 @@ impl<'a> PackComponentLoader<'a> {
entrypoint: Some(entrypoint), entrypoint: Some(entrypoint),
runtime: Some(sensor_runtime_id), runtime: Some(sensor_runtime_id),
runtime_ref: Some(sensor_runtime_ref.clone()), runtime_ref: Some(sensor_runtime_ref.clone()),
runtime_version_constraint: Some(runtime_version_constraint.clone()), runtime_version_constraint: Some(match runtime_version_constraint.clone() {
Some(value) => Patch::Set(value),
None => Patch::Clear,
}),
trigger: Some(trigger_id.unwrap_or(existing.trigger)), trigger: Some(trigger_id.unwrap_or(existing.trigger)),
trigger_ref: Some(trigger_ref.unwrap_or(existing.trigger_ref.clone())), trigger_ref: Some(trigger_ref.unwrap_or(existing.trigger_ref.clone())),
enabled: Some(enabled), enabled: Some(enabled),
param_schema, param_schema: Some(match param_schema {
Some(value) => Patch::Set(value),
None => Patch::Clear,
}),
config: Some(config), config: Some(config),
}; };

View File

@@ -6,7 +6,7 @@ use crate::models::{action::*, enums::PolicyMethod, Id, JsonSchema};
use crate::{Error, Result}; use crate::{Error, Result};
use sqlx::{Executor, Postgres, QueryBuilder}; use sqlx::{Executor, Postgres, QueryBuilder};
use super::{Create, Delete, FindById, FindByRef, List, Repository, Update}; use super::{Create, Delete, FindById, FindByRef, List, Patch, Repository, Update};
/// Columns selected in all Action queries. Must match the `Action` model's `FromRow` fields. /// Columns selected in all Action queries. Must match the `Action` model's `FromRow` fields.
pub const ACTION_COLUMNS: &str = "id, ref, pack, pack_ref, label, description, entrypoint, \ pub const ACTION_COLUMNS: &str = "id, ref, pack, pack_ref, label, description, entrypoint, \
@@ -67,7 +67,7 @@ pub struct UpdateActionInput {
pub description: Option<String>, pub description: Option<String>,
pub entrypoint: Option<String>, pub entrypoint: Option<String>,
pub runtime: Option<Id>, pub runtime: Option<Id>,
pub runtime_version_constraint: Option<Option<String>>, pub runtime_version_constraint: Option<Patch<String>>,
pub param_schema: Option<JsonSchema>, pub param_schema: Option<JsonSchema>,
pub out_schema: Option<JsonSchema>, pub out_schema: Option<JsonSchema>,
pub parameter_delivery: Option<String>, pub parameter_delivery: Option<String>,
@@ -237,7 +237,10 @@ impl Update for ActionRepository {
query.push(", "); query.push(", ");
} }
query.push("runtime_version_constraint = "); query.push("runtime_version_constraint = ");
query.push_bind(runtime_version_constraint); match runtime_version_constraint {
Patch::Set(value) => query.push_bind(value),
Patch::Clear => query.push_bind(Option::<String>::None),
};
has_updates = true; has_updates = true;
} }

View File

@@ -8,7 +8,7 @@ use crate::models::{
use crate::Result; use crate::Result;
use sqlx::{Executor, Postgres, QueryBuilder}; use sqlx::{Executor, Postgres, QueryBuilder};
use super::{Create, Delete, FindById, FindByRef, List, Repository, Update}; use super::{Create, Delete, FindById, FindByRef, List, Patch, Repository, Update};
// ============================================================================ // ============================================================================
// ArtifactRepository // ArtifactRepository
@@ -48,12 +48,12 @@ pub struct UpdateArtifactInput {
pub visibility: Option<ArtifactVisibility>, pub visibility: Option<ArtifactVisibility>,
pub retention_policy: Option<RetentionPolicyType>, pub retention_policy: Option<RetentionPolicyType>,
pub retention_limit: Option<i32>, pub retention_limit: Option<i32>,
pub name: Option<String>, pub name: Option<Patch<String>>,
pub description: Option<String>, pub description: Option<Patch<String>>,
pub content_type: Option<String>, pub content_type: Option<Patch<String>>,
pub size_bytes: Option<i64>, pub size_bytes: Option<i64>,
pub execution: Option<Option<i64>>, pub execution: Option<Patch<i64>>,
pub data: Option<serde_json::Value>, pub data: Option<Patch<serde_json::Value>>,
} }
/// Filters for searching artifacts /// Filters for searching artifacts
@@ -186,20 +186,62 @@ impl Update for ArtifactRepository {
push_field!(input.visibility, "visibility"); push_field!(input.visibility, "visibility");
push_field!(input.retention_policy, "retention_policy"); push_field!(input.retention_policy, "retention_policy");
push_field!(input.retention_limit, "retention_limit"); push_field!(input.retention_limit, "retention_limit");
push_field!(&input.name, "name"); if let Some(name) = &input.name {
push_field!(&input.description, "description"); if has_updates {
push_field!(&input.content_type, "content_type"); query.push(", ");
}
query.push("name = ");
match name {
Patch::Set(value) => query.push_bind(value),
Patch::Clear => query.push_bind(Option::<String>::None),
};
has_updates = true;
}
if let Some(description) = &input.description {
if has_updates {
query.push(", ");
}
query.push("description = ");
match description {
Patch::Set(value) => query.push_bind(value),
Patch::Clear => query.push_bind(Option::<String>::None),
};
has_updates = true;
}
if let Some(content_type) = &input.content_type {
if has_updates {
query.push(", ");
}
query.push("content_type = ");
match content_type {
Patch::Set(value) => query.push_bind(value),
Patch::Clear => query.push_bind(Option::<String>::None),
};
has_updates = true;
}
push_field!(input.size_bytes, "size_bytes"); push_field!(input.size_bytes, "size_bytes");
// execution is Option<Option<i64>> — outer Option = "was field provided?",
// inner Option = nullable column value
if let Some(exec_val) = input.execution { if let Some(exec_val) = input.execution {
if has_updates { if has_updates {
query.push(", "); query.push(", ");
} }
query.push("execution = ").push_bind(exec_val); query.push("execution = ");
match exec_val {
Patch::Set(value) => query.push_bind(value),
Patch::Clear => query.push_bind(Option::<i64>::None),
};
has_updates = true;
}
if let Some(data) = &input.data {
if has_updates {
query.push(", ");
}
query.push("data = ");
match data {
Patch::Set(value) => query.push_bind(value),
Patch::Clear => query.push_bind(Option::<serde_json::Value>::None),
};
has_updates = true; has_updates = true;
} }
push_field!(&input.data, "data");
if !has_updates { if !has_updates {
return Self::get_by_id(executor, id).await; return Self::get_by_id(executor, id).await;

View File

@@ -66,6 +66,14 @@ pub use runtime_version::RuntimeVersionRepository;
pub use trigger::{SensorRepository, TriggerRepository}; pub use trigger::{SensorRepository, TriggerRepository};
pub use workflow::{WorkflowDefinitionRepository, WorkflowExecutionRepository}; pub use workflow::{WorkflowDefinitionRepository, WorkflowExecutionRepository};
/// Explicit patch operation for update inputs where callers must distinguish
/// between "leave unchanged", "set value", and "clear to NULL".
#[derive(Debug, Clone, PartialEq)]
pub enum Patch<T> {
Set(T),
Clear,
}
/// Type alias for database connection/transaction /// Type alias for database connection/transaction
pub type DbConnection<'c> = &'c mut Transaction<'c, Postgres>; pub type DbConnection<'c> = &'c mut Transaction<'c, Postgres>;

View File

@@ -6,7 +6,7 @@ use crate::models::{pack::Pack, JsonDict, JsonSchema};
use crate::{Error, Result}; use crate::{Error, Result};
use sqlx::{Executor, Postgres, QueryBuilder}; use sqlx::{Executor, Postgres, QueryBuilder};
use super::{Create, Delete, FindById, FindByRef, List, Pagination, Repository, Update}; use super::{Create, Delete, FindById, FindByRef, List, Pagination, Patch, Repository, Update};
/// Repository for Pack operations /// Repository for Pack operations
pub struct PackRepository; pub struct PackRepository;
@@ -40,7 +40,7 @@ pub struct CreatePackInput {
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub struct UpdatePackInput { pub struct UpdatePackInput {
pub label: Option<String>, pub label: Option<String>,
pub description: Option<String>, pub description: Option<Patch<String>>,
pub version: Option<String>, pub version: Option<String>,
pub conf_schema: Option<JsonSchema>, pub conf_schema: Option<JsonSchema>,
pub config: Option<JsonDict>, pub config: Option<JsonDict>,
@@ -186,7 +186,10 @@ impl Update for PackRepository {
query.push(", "); query.push(", ");
} }
query.push("description = "); query.push("description = ");
query.push_bind(description); match description {
Patch::Set(value) => query.push_bind(value),
Patch::Clear => query.push_bind(Option::<String>::None),
};
has_updates = true; has_updates = true;
} }

View File

@@ -10,7 +10,7 @@ use crate::models::{
use crate::Result; use crate::Result;
use sqlx::{Executor, Postgres, QueryBuilder}; use sqlx::{Executor, Postgres, QueryBuilder};
use super::{Create, Delete, FindById, FindByRef, List, Repository, Update}; use super::{Create, Delete, FindById, FindByRef, List, Patch, Repository, Update};
/// Repository for Runtime operations /// Repository for Runtime operations
pub struct RuntimeRepository; pub struct RuntimeRepository;
@@ -39,10 +39,10 @@ pub struct CreateRuntimeInput {
/// Input for updating a runtime /// Input for updating a runtime
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub struct UpdateRuntimeInput { pub struct UpdateRuntimeInput {
pub description: Option<String>, pub description: Option<Patch<String>>,
pub name: Option<String>, pub name: Option<String>,
pub distributions: Option<JsonDict>, pub distributions: Option<JsonDict>,
pub installation: Option<JsonDict>, pub installation: Option<Patch<JsonDict>>,
pub execution_config: Option<JsonDict>, pub execution_config: Option<JsonDict>,
} }
@@ -163,7 +163,10 @@ impl Update for RuntimeRepository {
if let Some(description) = &input.description { if let Some(description) = &input.description {
query.push("description = "); query.push("description = ");
query.push_bind(description); match description {
Patch::Set(description) => query.push_bind(description),
Patch::Clear => query.push_bind(Option::<String>::None),
};
has_updates = true; has_updates = true;
} }
@@ -190,7 +193,10 @@ impl Update for RuntimeRepository {
query.push(", "); query.push(", ");
} }
query.push("installation = "); query.push("installation = ");
query.push_bind(installation); match installation {
Patch::Set(installation) => query.push_bind(installation),
Patch::Clear => query.push_bind(Option::<JsonDict>::None),
};
has_updates = true; has_updates = true;
} }

View File

@@ -5,7 +5,7 @@
use crate::error::Result; use crate::error::Result;
use crate::models::{Id, RuntimeVersion}; use crate::models::{Id, RuntimeVersion};
use crate::repositories::{Create, Delete, FindById, List, Repository, Update}; use crate::repositories::{Create, Delete, FindById, List, Patch, Repository, Update};
use sqlx::{Executor, Postgres, QueryBuilder}; use sqlx::{Executor, Postgres, QueryBuilder};
/// Repository for runtime version database operations /// Repository for runtime version database operations
@@ -39,14 +39,14 @@ pub struct CreateRuntimeVersionInput {
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub struct UpdateRuntimeVersionInput { pub struct UpdateRuntimeVersionInput {
pub version: Option<String>, pub version: Option<String>,
pub version_major: Option<Option<i32>>, pub version_major: Option<Patch<i32>>,
pub version_minor: Option<Option<i32>>, pub version_minor: Option<Patch<i32>>,
pub version_patch: Option<Option<i32>>, pub version_patch: Option<Patch<i32>>,
pub execution_config: Option<serde_json::Value>, pub execution_config: Option<serde_json::Value>,
pub distributions: Option<serde_json::Value>, pub distributions: Option<serde_json::Value>,
pub is_default: Option<bool>, pub is_default: Option<bool>,
pub available: Option<bool>, pub available: Option<bool>,
pub verified_at: Option<Option<chrono::DateTime<chrono::Utc>>>, pub verified_at: Option<Patch<chrono::DateTime<chrono::Utc>>>,
pub meta: Option<serde_json::Value>, pub meta: Option<serde_json::Value>,
} }
@@ -154,7 +154,10 @@ impl Update for RuntimeVersionRepository {
query.push(", "); query.push(", ");
} }
query.push("version_major = "); query.push("version_major = ");
query.push_bind(*version_major); match version_major {
Patch::Set(value) => query.push_bind(*value),
Patch::Clear => query.push_bind(Option::<i32>::None),
};
has_updates = true; has_updates = true;
} }
@@ -163,7 +166,10 @@ impl Update for RuntimeVersionRepository {
query.push(", "); query.push(", ");
} }
query.push("version_minor = "); query.push("version_minor = ");
query.push_bind(*version_minor); match version_minor {
Patch::Set(value) => query.push_bind(*value),
Patch::Clear => query.push_bind(Option::<i32>::None),
};
has_updates = true; has_updates = true;
} }
@@ -172,7 +178,10 @@ impl Update for RuntimeVersionRepository {
query.push(", "); query.push(", ");
} }
query.push("version_patch = "); query.push("version_patch = ");
query.push_bind(*version_patch); match version_patch {
Patch::Set(value) => query.push_bind(*value),
Patch::Clear => query.push_bind(Option::<i32>::None),
};
has_updates = true; has_updates = true;
} }
@@ -217,7 +226,10 @@ impl Update for RuntimeVersionRepository {
query.push(", "); query.push(", ");
} }
query.push("verified_at = "); query.push("verified_at = ");
query.push_bind(*verified_at); match verified_at {
Patch::Set(value) => query.push_bind(*value),
Patch::Clear => query.push_bind(Option::<chrono::DateTime<chrono::Utc>>::None),
};
has_updates = true; has_updates = true;
} }

View File

@@ -7,7 +7,7 @@ use crate::Result;
use serde_json::Value as JsonValue; use serde_json::Value as JsonValue;
use sqlx::{Executor, Postgres, QueryBuilder}; use sqlx::{Executor, Postgres, QueryBuilder};
use super::{Create, Delete, FindById, FindByRef, List, Repository, Update}; use super::{Create, Delete, FindById, FindByRef, List, Patch, Repository, Update};
// ============================================================================ // ============================================================================
// Trigger Search // Trigger Search
@@ -88,10 +88,10 @@ pub struct CreateTriggerInput {
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub struct UpdateTriggerInput { pub struct UpdateTriggerInput {
pub label: Option<String>, pub label: Option<String>,
pub description: Option<String>, pub description: Option<Patch<String>>,
pub enabled: Option<bool>, pub enabled: Option<bool>,
pub param_schema: Option<JsonSchema>, pub param_schema: Option<Patch<JsonSchema>>,
pub out_schema: Option<JsonSchema>, pub out_schema: Option<Patch<JsonSchema>>,
} }
#[async_trait::async_trait] #[async_trait::async_trait]
@@ -229,7 +229,10 @@ impl Update for TriggerRepository {
query.push(", "); query.push(", ");
} }
query.push("description = "); query.push("description = ");
query.push_bind(description); match description {
Patch::Set(value) => query.push_bind(value),
Patch::Clear => query.push_bind(Option::<String>::None),
};
has_updates = true; has_updates = true;
} }
@@ -247,7 +250,10 @@ impl Update for TriggerRepository {
query.push(", "); query.push(", ");
} }
query.push("param_schema = "); query.push("param_schema = ");
query.push_bind(param_schema); match param_schema {
Patch::Set(value) => query.push_bind(value),
Patch::Clear => query.push_bind(Option::<JsonSchema>::None),
};
has_updates = true; has_updates = true;
} }
@@ -256,7 +262,10 @@ impl Update for TriggerRepository {
query.push(", "); query.push(", ");
} }
query.push("out_schema = "); query.push("out_schema = ");
query.push_bind(out_schema); match out_schema {
Patch::Set(value) => query.push_bind(value),
Patch::Clear => query.push_bind(Option::<JsonSchema>::None),
};
has_updates = true; has_updates = true;
} }
@@ -676,11 +685,11 @@ pub struct UpdateSensorInput {
pub entrypoint: Option<String>, pub entrypoint: Option<String>,
pub runtime: Option<Id>, pub runtime: Option<Id>,
pub runtime_ref: Option<String>, pub runtime_ref: Option<String>,
pub runtime_version_constraint: Option<Option<String>>, pub runtime_version_constraint: Option<Patch<String>>,
pub trigger: Option<Id>, pub trigger: Option<Id>,
pub trigger_ref: Option<String>, pub trigger_ref: Option<String>,
pub enabled: Option<bool>, pub enabled: Option<bool>,
pub param_schema: Option<JsonSchema>, pub param_schema: Option<Patch<JsonSchema>>,
pub config: Option<JsonValue>, pub config: Option<JsonValue>,
} }
@@ -866,7 +875,10 @@ impl Update for SensorRepository {
query.push(", "); query.push(", ");
} }
query.push("runtime_version_constraint = "); query.push("runtime_version_constraint = ");
query.push_bind(runtime_version_constraint); match runtime_version_constraint {
Patch::Set(value) => query.push_bind(value),
Patch::Clear => query.push_bind(Option::<String>::None),
};
has_updates = true; has_updates = true;
} }
@@ -893,7 +905,10 @@ impl Update for SensorRepository {
query.push(", "); query.push(", ");
} }
query.push("param_schema = "); query.push("param_schema = ");
query.push_bind(param_schema); match param_schema {
Patch::Set(value) => query.push_bind(value),
Patch::Clear => query.push_bind(Option::<JsonSchema>::None),
};
has_updates = true; has_updates = true;
} }

View File

@@ -6,7 +6,9 @@
mod helpers; mod helpers;
use attune_common::repositories::pack::{self, PackRepository}; use attune_common::repositories::pack::{self, PackRepository};
use attune_common::repositories::{Create, Delete, FindById, FindByRef, List, Pagination, Update}; use attune_common::repositories::{
Create, Delete, FindById, FindByRef, List, Pagination, Patch, Update,
};
use attune_common::Error; use attune_common::Error;
use helpers::*; use helpers::*;
use serde_json::json; use serde_json::json;
@@ -214,7 +216,7 @@ async fn test_update_pack() {
let update_input = pack::UpdatePackInput { let update_input = pack::UpdatePackInput {
label: Some("Updated Label".to_string()), label: Some("Updated Label".to_string()),
version: Some("2.0.0".to_string()), version: Some("2.0.0".to_string()),
description: Some("Updated description".to_string()), description: Some(Patch::Set("Updated description".to_string())),
..Default::default() ..Default::default()
}; };

View File

@@ -9,7 +9,7 @@ use attune_common::models::enums::{
use attune_common::repositories::artifact::{ use attune_common::repositories::artifact::{
ArtifactRepository, CreateArtifactInput, UpdateArtifactInput, ArtifactRepository, CreateArtifactInput, UpdateArtifactInput,
}; };
use attune_common::repositories::{Create, Delete, FindById, FindByRef, List, Update}; use attune_common::repositories::{Create, Delete, FindById, FindByRef, List, Patch, Update};
use attune_common::Error; use attune_common::Error;
use sqlx::PgPool; use sqlx::PgPool;
use std::collections::hash_map::DefaultHasher; use std::collections::hash_map::DefaultHasher;
@@ -267,11 +267,11 @@ async fn test_update_artifact_all_fields() {
visibility: Some(ArtifactVisibility::Public), visibility: Some(ArtifactVisibility::Public),
retention_policy: Some(RetentionPolicyType::Days), retention_policy: Some(RetentionPolicyType::Days),
retention_limit: Some(30), retention_limit: Some(30),
name: Some("Updated Name".to_string()), name: Some(Patch::Set("Updated Name".to_string())),
description: Some("Updated description".to_string()), description: Some(Patch::Set("Updated description".to_string())),
content_type: Some("image/png".to_string()), content_type: Some(Patch::Set("image/png".to_string())),
size_bytes: Some(12345), size_bytes: Some(12345),
data: Some(serde_json::json!({"key": "value"})), data: Some(Patch::Set(serde_json::json!({"key": "value"}))),
execution: None, execution: None,
}; };

View File

@@ -6,7 +6,7 @@
use attune_common::repositories::runtime::{ use attune_common::repositories::runtime::{
CreateRuntimeInput, RuntimeRepository, UpdateRuntimeInput, CreateRuntimeInput, RuntimeRepository, UpdateRuntimeInput,
}; };
use attune_common::repositories::{Create, Delete, FindById, FindByRef, List, Update}; use attune_common::repositories::{Create, Delete, FindById, FindByRef, List, Patch, Update};
use serde_json::json; use serde_json::json;
use sqlx::PgPool; use sqlx::PgPool;
use std::collections::hash_map::DefaultHasher; use std::collections::hash_map::DefaultHasher;
@@ -259,14 +259,14 @@ async fn test_update_runtime() {
.expect("Failed to create runtime"); .expect("Failed to create runtime");
let update_input = UpdateRuntimeInput { let update_input = UpdateRuntimeInput {
description: Some("Updated description".to_string()), description: Some(Patch::Set("Updated description".to_string())),
name: Some("updated_name".to_string()), name: Some("updated_name".to_string()),
distributions: Some(json!({ distributions: Some(json!({
"linux": { "supported": false } "linux": { "supported": false }
})), })),
installation: Some(json!({ installation: Some(Patch::Set(json!({
"method": "npm" "method": "npm"
})), }))),
execution_config: None, execution_config: None,
}; };
@@ -275,10 +275,10 @@ async fn test_update_runtime() {
.expect("Failed to update runtime"); .expect("Failed to update runtime");
assert_eq!(updated.id, created.id); assert_eq!(updated.id, created.id);
assert_eq!(updated.description, update_input.description); assert_eq!(updated.description, Some("Updated description".to_string()));
assert_eq!(updated.name, update_input.name.unwrap()); assert_eq!(updated.name, update_input.name.unwrap());
assert_eq!(updated.distributions, update_input.distributions.unwrap()); assert_eq!(updated.distributions, update_input.distributions.unwrap());
assert_eq!(updated.installation, update_input.installation); assert_eq!(updated.installation, Some(json!({ "method": "npm" })));
assert!(updated.updated > created.updated); assert!(updated.updated > created.updated);
} }
@@ -294,7 +294,7 @@ async fn test_update_runtime_partial() {
.expect("Failed to create runtime"); .expect("Failed to create runtime");
let update_input = UpdateRuntimeInput { let update_input = UpdateRuntimeInput {
description: Some("Only description changed".to_string()), description: Some(Patch::Set("Only description changed".to_string())),
name: None, name: None,
distributions: None, distributions: None,
installation: None, installation: None,
@@ -305,7 +305,10 @@ async fn test_update_runtime_partial() {
.await .await
.expect("Failed to update runtime"); .expect("Failed to update runtime");
assert_eq!(updated.description, update_input.description); assert_eq!(
updated.description,
Some("Only description changed".to_string())
);
assert_eq!(updated.name, created.name); assert_eq!(updated.name, created.name);
assert_eq!(updated.distributions, created.distributions); assert_eq!(updated.distributions, created.distributions);
assert_eq!(updated.installation, created.installation); assert_eq!(updated.installation, created.installation);
@@ -610,7 +613,7 @@ async fn test_update_changes_timestamp() {
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await; tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
let update_input = UpdateRuntimeInput { let update_input = UpdateRuntimeInput {
description: Some("Updated".to_string()), description: Some(Patch::Set("Updated".to_string())),
..Default::default() ..Default::default()
}; };

View File

@@ -8,7 +8,7 @@ mod helpers;
use attune_common::{ use attune_common::{
repositories::{ repositories::{
trigger::{CreateSensorInput, SensorRepository, UpdateSensorInput}, trigger::{CreateSensorInput, SensorRepository, UpdateSensorInput},
Create, Delete, FindById, FindByRef, List, Update, Create, Delete, FindById, FindByRef, List, Patch, Update,
}, },
Error, Error,
}; };
@@ -888,7 +888,7 @@ async fn test_update_param_schema() {
}); });
let input = UpdateSensorInput { let input = UpdateSensorInput {
param_schema: Some(new_schema.clone()), param_schema: Some(Patch::Set(new_schema.clone())),
..Default::default() ..Default::default()
}; };
@@ -937,7 +937,7 @@ async fn test_update_multiple_fields() {
description: Some("Updated multiple fields".to_string()), description: Some("Updated multiple fields".to_string()),
entrypoint: Some("sensors/multi.py".to_string()), entrypoint: Some("sensors/multi.py".to_string()),
enabled: Some(false), enabled: Some(false),
param_schema: Some(json!({"type": "object"})), param_schema: Some(Patch::Set(json!({"type": "object"}))),
..Default::default() ..Default::default()
}; };
@@ -1766,7 +1766,7 @@ async fn test_param_schema_can_be_null() {
// Update to add schema // Update to add schema
let schema = json!({"type": "object"}); let schema = json!({"type": "object"});
let input = UpdateSensorInput { let input = UpdateSensorInput {
param_schema: Some(schema.clone()), param_schema: Some(Patch::Set(schema.clone())),
..Default::default() ..Default::default()
}; };

View File

@@ -8,7 +8,7 @@ mod helpers;
use attune_common::{ use attune_common::{
repositories::{ repositories::{
trigger::{CreateTriggerInput, TriggerRepository, UpdateTriggerInput}, trigger::{CreateTriggerInput, TriggerRepository, UpdateTriggerInput},
Create, Delete, FindById, FindByRef, List, Update, Create, Delete, FindById, FindByRef, List, Patch, Update,
}, },
Error, Error,
}; };
@@ -477,7 +477,7 @@ async fn test_update_trigger() {
let update_input = UpdateTriggerInput { let update_input = UpdateTriggerInput {
label: Some("Updated Label".to_string()), label: Some("Updated Label".to_string()),
description: Some("Updated description".to_string()), description: Some(Patch::Set("Updated description".to_string())),
enabled: Some(false), enabled: Some(false),
param_schema: None, param_schema: None,
out_schema: None, out_schema: None,
@@ -571,8 +571,8 @@ async fn test_update_trigger_schemas() {
label: None, label: None,
description: None, description: None,
enabled: None, enabled: None,
param_schema: Some(new_param_schema.clone()), param_schema: Some(Patch::Set(new_param_schema.clone())),
out_schema: Some(new_out_schema.clone()), out_schema: Some(Patch::Set(new_out_schema.clone())),
}; };
let updated = TriggerRepository::update(&pool, trigger.id, update_input) let updated = TriggerRepository::update(&pool, trigger.id, update_input)

View File

@@ -16,6 +16,7 @@ const PackRegisterPage = lazy(() => import("@/pages/packs/PackRegisterPage"));
const PackInstallPage = lazy(() => import("@/pages/packs/PackInstallPage")); const PackInstallPage = lazy(() => import("@/pages/packs/PackInstallPage"));
const PackEditPage = lazy(() => import("@/pages/packs/PackEditPage")); const PackEditPage = lazy(() => import("@/pages/packs/PackEditPage"));
const ActionsPage = lazy(() => import("@/pages/actions/ActionsPage")); const ActionsPage = lazy(() => import("@/pages/actions/ActionsPage"));
const RuntimesPage = lazy(() => import("@/pages/runtimes/RuntimesPage"));
const WorkflowBuilderPage = lazy( const WorkflowBuilderPage = lazy(
() => import("@/pages/actions/WorkflowBuilderPage"), () => import("@/pages/actions/WorkflowBuilderPage"),
); );
@@ -85,6 +86,9 @@ function App() {
<Route path="packs/:ref" element={<PacksPage />} /> <Route path="packs/:ref" element={<PacksPage />} />
<Route path="packs/:ref/edit" element={<PackEditPage />} /> <Route path="packs/:ref/edit" element={<PackEditPage />} />
<Route path="actions" element={<ActionsPage />} /> <Route path="actions" element={<ActionsPage />} />
<Route path="runtimes" element={<RuntimesPage />} />
<Route path="runtimes/new" element={<RuntimesPage />} />
<Route path="runtimes/:ref" element={<RuntimesPage />} />
<Route <Route
path="actions/workflows/new" path="actions/workflows/new"
element={<WorkflowBuilderPage />} element={<WorkflowBuilderPage />}

View File

@@ -1,32 +1,32 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
import type { ApiRequestOptions } from "./ApiRequestOptions"; import type { ApiRequestOptions } from './ApiRequestOptions';
type Resolver<T> = (options: ApiRequestOptions) => Promise<T>; type Resolver<T> = (options: ApiRequestOptions) => Promise<T>;
type Headers = Record<string, string>; type Headers = Record<string, string>;
export type OpenAPIConfig = { export type OpenAPIConfig = {
BASE: string; BASE: string;
VERSION: string; VERSION: string;
WITH_CREDENTIALS: boolean; WITH_CREDENTIALS: boolean;
CREDENTIALS: "include" | "omit" | "same-origin"; CREDENTIALS: 'include' | 'omit' | 'same-origin';
TOKEN?: string | Resolver<string> | undefined; TOKEN?: string | Resolver<string> | undefined;
USERNAME?: string | Resolver<string> | undefined; USERNAME?: string | Resolver<string> | undefined;
PASSWORD?: string | Resolver<string> | undefined; PASSWORD?: string | Resolver<string> | undefined;
HEADERS?: Headers | Resolver<Headers> | undefined; HEADERS?: Headers | Resolver<Headers> | undefined;
ENCODE_PATH?: ((path: string) => string) | undefined; ENCODE_PATH?: ((path: string) => string) | undefined;
}; };
export const OpenAPI: OpenAPIConfig = { export const OpenAPI: OpenAPIConfig = {
BASE: "http://localhost:8080", BASE: 'http://localhost:8080',
VERSION: "0.1.0", VERSION: '0.1.0',
WITH_CREDENTIALS: false, WITH_CREDENTIALS: false,
CREDENTIALS: "include", CREDENTIALS: 'include',
TOKEN: undefined, TOKEN: undefined,
USERNAME: undefined, USERNAME: undefined,
PASSWORD: undefined, PASSWORD: undefined,
HEADERS: undefined, HEADERS: undefined,
ENCODE_PATH: undefined, ENCODE_PATH: undefined,
}; };

View File

@@ -1,124 +1,143 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
export { ApiError } from './core/ApiError';
export { CancelablePromise, CancelError } from './core/CancelablePromise';
export { OpenAPI } from './core/OpenAPI';
export type { OpenAPIConfig } from './core/OpenAPI';
export { ApiError } from "./core/ApiError"; export type { ActionResponse } from './models/ActionResponse';
export { CancelablePromise, CancelError } from "./core/CancelablePromise"; export type { ActionSummary } from './models/ActionSummary';
export { OpenAPI } from "./core/OpenAPI"; export type { ApiResponse_ActionResponse } from './models/ApiResponse_ActionResponse';
export type { OpenAPIConfig } from "./core/OpenAPI"; export type { ApiResponse_CurrentUserResponse } from './models/ApiResponse_CurrentUserResponse';
export type { ApiResponse_EnforcementResponse } from './models/ApiResponse_EnforcementResponse';
export type { ApiResponse_EventResponse } from './models/ApiResponse_EventResponse';
export type { ApiResponse_ExecutionResponse } from './models/ApiResponse_ExecutionResponse';
export type { ApiResponse_IdentitySummary } from './models/ApiResponse_IdentitySummary';
export type { ApiResponse_InquiryResponse } from './models/ApiResponse_InquiryResponse';
export type { ApiResponse_KeyResponse } from './models/ApiResponse_KeyResponse';
export type { ApiResponse_PackInstallResponse } from './models/ApiResponse_PackInstallResponse';
export type { ApiResponse_PackResponse } from './models/ApiResponse_PackResponse';
export type { ApiResponse_PermissionAssignmentResponse } from './models/ApiResponse_PermissionAssignmentResponse';
export type { ApiResponse_QueueStatsResponse } from './models/ApiResponse_QueueStatsResponse';
export type { ApiResponse_RuleResponse } from './models/ApiResponse_RuleResponse';
export type { ApiResponse_RuntimeResponse } from './models/ApiResponse_RuntimeResponse';
export type { ApiResponse_SensorResponse } from './models/ApiResponse_SensorResponse';
export type { ApiResponse_String } from './models/ApiResponse_String';
export type { ApiResponse_TokenResponse } from './models/ApiResponse_TokenResponse';
export type { ApiResponse_TriggerResponse } from './models/ApiResponse_TriggerResponse';
export type { ApiResponse_WebhookReceiverResponse } from './models/ApiResponse_WebhookReceiverResponse';
export type { ApiResponse_WorkflowResponse } from './models/ApiResponse_WorkflowResponse';
export type { ChangePasswordRequest } from './models/ChangePasswordRequest';
export type { CreateActionRequest } from './models/CreateActionRequest';
export type { CreateIdentityRequest } from './models/CreateIdentityRequest';
export type { CreateInquiryRequest } from './models/CreateInquiryRequest';
export type { CreateKeyRequest } from './models/CreateKeyRequest';
export type { CreatePackRequest } from './models/CreatePackRequest';
export type { CreatePermissionAssignmentRequest } from './models/CreatePermissionAssignmentRequest';
export type { CreateRuleRequest } from './models/CreateRuleRequest';
export type { CreateRuntimeRequest } from './models/CreateRuntimeRequest';
export type { CreateSensorRequest } from './models/CreateSensorRequest';
export type { CreateTriggerRequest } from './models/CreateTriggerRequest';
export type { CreateWorkflowRequest } from './models/CreateWorkflowRequest';
export type { CurrentUserResponse } from './models/CurrentUserResponse';
export { EnforcementCondition } from './models/EnforcementCondition';
export type { EnforcementResponse } from './models/EnforcementResponse';
export { EnforcementStatus } from './models/EnforcementStatus';
export type { EnforcementSummary } from './models/EnforcementSummary';
export type { EventResponse } from './models/EventResponse';
export type { EventSummary } from './models/EventSummary';
export type { ExecutionResponse } from './models/ExecutionResponse';
export { ExecutionStatus } from './models/ExecutionStatus';
export type { ExecutionSummary } from './models/ExecutionSummary';
export type { HealthResponse } from './models/HealthResponse';
export type { i64 } from './models/i64';
export type { IdentitySummary } from './models/IdentitySummary';
export type { InquiryRespondRequest } from './models/InquiryRespondRequest';
export type { InquiryResponse } from './models/InquiryResponse';
export { InquiryStatus } from './models/InquiryStatus';
export type { InquirySummary } from './models/InquirySummary';
export type { InstallPackRequest } from './models/InstallPackRequest';
export type { KeyResponse } from './models/KeyResponse';
export type { KeySummary } from './models/KeySummary';
export type { LoginRequest } from './models/LoginRequest';
export { NullableJsonPatch } from './models/NullableJsonPatch';
export { NullableStringPatch } from './models/NullableStringPatch';
export { OwnerType } from './models/OwnerType';
export type { PackInstallResponse } from './models/PackInstallResponse';
export type { PackResponse } from './models/PackResponse';
export type { PackSummary } from './models/PackSummary';
export type { PackTestExecution } from './models/PackTestExecution';
export type { PackTestResult } from './models/PackTestResult';
export type { PackTestSummary } from './models/PackTestSummary';
export type { PackWorkflowSyncResponse } from './models/PackWorkflowSyncResponse';
export type { PackWorkflowValidationResponse } from './models/PackWorkflowValidationResponse';
export type { PaginatedResponse_ActionSummary } from './models/PaginatedResponse_ActionSummary';
export type { PaginatedResponse_EnforcementSummary } from './models/PaginatedResponse_EnforcementSummary';
export type { PaginatedResponse_EventSummary } from './models/PaginatedResponse_EventSummary';
export type { PaginatedResponse_ExecutionSummary } from './models/PaginatedResponse_ExecutionSummary';
export type { PaginatedResponse_IdentitySummary } from './models/PaginatedResponse_IdentitySummary';
export type { PaginatedResponse_InquirySummary } from './models/PaginatedResponse_InquirySummary';
export type { PaginatedResponse_KeySummary } from './models/PaginatedResponse_KeySummary';
export type { PaginatedResponse_PackSummary } from './models/PaginatedResponse_PackSummary';
export type { PaginatedResponse_PackTestSummary } from './models/PaginatedResponse_PackTestSummary';
export type { PaginatedResponse_RuleSummary } from './models/PaginatedResponse_RuleSummary';
export type { PaginatedResponse_RuntimeSummary } from './models/PaginatedResponse_RuntimeSummary';
export type { PaginatedResponse_SensorSummary } from './models/PaginatedResponse_SensorSummary';
export type { PaginatedResponse_TriggerSummary } from './models/PaginatedResponse_TriggerSummary';
export type { PaginatedResponse_WorkflowSummary } from './models/PaginatedResponse_WorkflowSummary';
export type { PaginationMeta } from './models/PaginationMeta';
export type { PermissionAssignmentResponse } from './models/PermissionAssignmentResponse';
export type { PermissionSetSummary } from './models/PermissionSetSummary';
export type { QueueStatsResponse } from './models/QueueStatsResponse';
export type { RefreshTokenRequest } from './models/RefreshTokenRequest';
export type { RegisterPackRequest } from './models/RegisterPackRequest';
export type { RegisterRequest } from './models/RegisterRequest';
export type { RuleResponse } from './models/RuleResponse';
export type { RuleSummary } from './models/RuleSummary';
export type { RuntimeResponse } from './models/RuntimeResponse';
export type { RuntimeSummary } from './models/RuntimeSummary';
export type { SensorResponse } from './models/SensorResponse';
export type { SensorSummary } from './models/SensorSummary';
export type { SuccessResponse } from './models/SuccessResponse';
export type { TestCaseResult } from './models/TestCaseResult';
export { TestStatus } from './models/TestStatus';
export type { TestSuiteResult } from './models/TestSuiteResult';
export type { TokenResponse } from './models/TokenResponse';
export type { TriggerResponse } from './models/TriggerResponse';
export type { TriggerSummary } from './models/TriggerSummary';
export type { UpdateActionRequest } from './models/UpdateActionRequest';
export type { UpdateIdentityRequest } from './models/UpdateIdentityRequest';
export type { UpdateInquiryRequest } from './models/UpdateInquiryRequest';
export type { UpdateKeyRequest } from './models/UpdateKeyRequest';
export type { UpdatePackRequest } from './models/UpdatePackRequest';
export type { UpdateRuleRequest } from './models/UpdateRuleRequest';
export type { UpdateRuntimeRequest } from './models/UpdateRuntimeRequest';
export type { UpdateSensorRequest } from './models/UpdateSensorRequest';
export type { UpdateTriggerRequest } from './models/UpdateTriggerRequest';
export type { UpdateWorkflowRequest } from './models/UpdateWorkflowRequest';
export type { UserInfo } from './models/UserInfo';
export type { Value } from './models/Value';
export type { WebhookReceiverRequest } from './models/WebhookReceiverRequest';
export type { WebhookReceiverResponse } from './models/WebhookReceiverResponse';
export type { WorkflowResponse } from './models/WorkflowResponse';
export type { WorkflowSummary } from './models/WorkflowSummary';
export type { WorkflowSyncResult } from './models/WorkflowSyncResult';
export type { ActionResponse } from "./models/ActionResponse"; export { ActionsService } from './services/ActionsService';
export type { ActionSummary } from "./models/ActionSummary"; export { AuthService } from './services/AuthService';
export type { ApiResponse_ActionResponse } from "./models/ApiResponse_ActionResponse"; export { EnforcementsService } from './services/EnforcementsService';
export type { ApiResponse_CurrentUserResponse } from "./models/ApiResponse_CurrentUserResponse"; export { EventsService } from './services/EventsService';
export type { ApiResponse_EnforcementResponse } from "./models/ApiResponse_EnforcementResponse"; export { ExecutionsService } from './services/ExecutionsService';
export type { ApiResponse_EventResponse } from "./models/ApiResponse_EventResponse"; export { HealthService } from './services/HealthService';
export type { ApiResponse_ExecutionResponse } from "./models/ApiResponse_ExecutionResponse"; export { InquiriesService } from './services/InquiriesService';
export type { ApiResponse_InquiryResponse } from "./models/ApiResponse_InquiryResponse"; export { PacksService } from './services/PacksService';
export type { ApiResponse_KeyResponse } from "./models/ApiResponse_KeyResponse"; export { PermissionsService } from './services/PermissionsService';
export type { ApiResponse_PackInstallResponse } from "./models/ApiResponse_PackInstallResponse"; export { RulesService } from './services/RulesService';
export type { ApiResponse_PackResponse } from "./models/ApiResponse_PackResponse"; export { RuntimesService } from './services/RuntimesService';
export type { ApiResponse_QueueStatsResponse } from "./models/ApiResponse_QueueStatsResponse"; export { SecretsService } from './services/SecretsService';
export type { ApiResponse_RuleResponse } from "./models/ApiResponse_RuleResponse"; export { SensorsService } from './services/SensorsService';
export type { ApiResponse_SensorResponse } from "./models/ApiResponse_SensorResponse"; export { TriggersService } from './services/TriggersService';
export type { ApiResponse_String } from "./models/ApiResponse_String"; export { WebhooksService } from './services/WebhooksService';
export type { ApiResponse_TokenResponse } from "./models/ApiResponse_TokenResponse"; export { WorkflowsService } from './services/WorkflowsService';
export type { ApiResponse_TriggerResponse } from "./models/ApiResponse_TriggerResponse";
export type { ApiResponse_WebhookReceiverResponse } from "./models/ApiResponse_WebhookReceiverResponse";
export type { ApiResponse_WorkflowResponse } from "./models/ApiResponse_WorkflowResponse";
export type { ChangePasswordRequest } from "./models/ChangePasswordRequest";
export type { CreateActionRequest } from "./models/CreateActionRequest";
export type { CreateInquiryRequest } from "./models/CreateInquiryRequest";
export type { CreateKeyRequest } from "./models/CreateKeyRequest";
export type { CreatePackRequest } from "./models/CreatePackRequest";
export type { CreateRuleRequest } from "./models/CreateRuleRequest";
export type { CreateSensorRequest } from "./models/CreateSensorRequest";
export type { CreateTriggerRequest } from "./models/CreateTriggerRequest";
export type { CreateWorkflowRequest } from "./models/CreateWorkflowRequest";
export type { CurrentUserResponse } from "./models/CurrentUserResponse";
export { EnforcementCondition } from "./models/EnforcementCondition";
export type { EnforcementResponse } from "./models/EnforcementResponse";
export { EnforcementStatus } from "./models/EnforcementStatus";
export type { EnforcementSummary } from "./models/EnforcementSummary";
export type { EventResponse } from "./models/EventResponse";
export type { EventSummary } from "./models/EventSummary";
export type { ExecutionResponse } from "./models/ExecutionResponse";
export { ExecutionStatus } from "./models/ExecutionStatus";
export type { ExecutionSummary } from "./models/ExecutionSummary";
export type { HealthResponse } from "./models/HealthResponse";
export type { i64 } from "./models/i64";
export type { InquiryRespondRequest } from "./models/InquiryRespondRequest";
export type { InquiryResponse } from "./models/InquiryResponse";
export { InquiryStatus } from "./models/InquiryStatus";
export type { InquirySummary } from "./models/InquirySummary";
export type { InstallPackRequest } from "./models/InstallPackRequest";
export type { KeyResponse } from "./models/KeyResponse";
export type { KeySummary } from "./models/KeySummary";
export type { LoginRequest } from "./models/LoginRequest";
export { OwnerType } from "./models/OwnerType";
export type { PackInstallResponse } from "./models/PackInstallResponse";
export type { PackResponse } from "./models/PackResponse";
export type { PackSummary } from "./models/PackSummary";
export type { PackTestExecution } from "./models/PackTestExecution";
export type { PackTestResult } from "./models/PackTestResult";
export type { PackTestSummary } from "./models/PackTestSummary";
export type { PackWorkflowSyncResponse } from "./models/PackWorkflowSyncResponse";
export type { PackWorkflowValidationResponse } from "./models/PackWorkflowValidationResponse";
export type { PaginatedResponse_ActionSummary } from "./models/PaginatedResponse_ActionSummary";
export type { PaginatedResponse_EnforcementSummary } from "./models/PaginatedResponse_EnforcementSummary";
export type { PaginatedResponse_EventSummary } from "./models/PaginatedResponse_EventSummary";
export type { PaginatedResponse_ExecutionSummary } from "./models/PaginatedResponse_ExecutionSummary";
export type { PaginatedResponse_InquirySummary } from "./models/PaginatedResponse_InquirySummary";
export type { PaginatedResponse_KeySummary } from "./models/PaginatedResponse_KeySummary";
export type { PaginatedResponse_PackSummary } from "./models/PaginatedResponse_PackSummary";
export type { PaginatedResponse_PackTestSummary } from "./models/PaginatedResponse_PackTestSummary";
export type { PaginatedResponse_RuleSummary } from "./models/PaginatedResponse_RuleSummary";
export type { PaginatedResponse_SensorSummary } from "./models/PaginatedResponse_SensorSummary";
export type { PaginatedResponse_TriggerSummary } from "./models/PaginatedResponse_TriggerSummary";
export type { PaginatedResponse_WorkflowSummary } from "./models/PaginatedResponse_WorkflowSummary";
export type { PaginationMeta } from "./models/PaginationMeta";
export type { QueueStatsResponse } from "./models/QueueStatsResponse";
export type { RefreshTokenRequest } from "./models/RefreshTokenRequest";
export type { RegisterPackRequest } from "./models/RegisterPackRequest";
export type { RegisterRequest } from "./models/RegisterRequest";
export type { RuleResponse } from "./models/RuleResponse";
export type { RuleSummary } from "./models/RuleSummary";
export type { SensorResponse } from "./models/SensorResponse";
export type { SensorSummary } from "./models/SensorSummary";
export type { SuccessResponse } from "./models/SuccessResponse";
export type { TestCaseResult } from "./models/TestCaseResult";
export { TestStatus } from "./models/TestStatus";
export type { TestSuiteResult } from "./models/TestSuiteResult";
export type { TokenResponse } from "./models/TokenResponse";
export type { TriggerResponse } from "./models/TriggerResponse";
export type { TriggerSummary } from "./models/TriggerSummary";
export type { UpdateActionRequest } from "./models/UpdateActionRequest";
export type { UpdateInquiryRequest } from "./models/UpdateInquiryRequest";
export type { UpdateKeyRequest } from "./models/UpdateKeyRequest";
export type { UpdatePackRequest } from "./models/UpdatePackRequest";
export type { UpdateRuleRequest } from "./models/UpdateRuleRequest";
export type { UpdateSensorRequest } from "./models/UpdateSensorRequest";
export type { UpdateTriggerRequest } from "./models/UpdateTriggerRequest";
export type { UpdateWorkflowRequest } from "./models/UpdateWorkflowRequest";
export type { UserInfo } from "./models/UserInfo";
export type { Value } from "./models/Value";
export type { WebhookReceiverRequest } from "./models/WebhookReceiverRequest";
export type { WebhookReceiverResponse } from "./models/WebhookReceiverResponse";
export type { WorkflowResponse } from "./models/WorkflowResponse";
export type { WorkflowSummary } from "./models/WorkflowSummary";
export type { WorkflowSyncResult } from "./models/WorkflowSyncResult";
export { ActionsService } from "./services/ActionsService";
export { AuthService } from "./services/AuthService";
export { EnforcementsService } from "./services/EnforcementsService";
export { EventsService } from "./services/EventsService";
export { ExecutionsService } from "./services/ExecutionsService";
export { HealthService } from "./services/HealthService";
export { InquiriesService } from "./services/InquiriesService";
export { PacksService } from "./services/PacksService";
export { RulesService } from "./services/RulesService";
export { SecretsService } from "./services/SecretsService";
export { SensorsService } from "./services/SensorsService";
export { TriggersService } from "./services/TriggersService";
export { WebhooksService } from "./services/WebhooksService";
export { WorkflowsService } from "./services/WorkflowsService";

View File

@@ -6,64 +6,65 @@
* Response DTO for action information * Response DTO for action information
*/ */
export type ActionResponse = { export type ActionResponse = {
/** /**
* Creation timestamp * Creation timestamp
*/ */
created: string; created: string;
/** /**
* Action description * Action description
*/ */
description: string; description: string;
/** /**
* Entry point * Entry point
*/ */
entrypoint: string; entrypoint: string;
/** /**
* Action ID * Action ID
*/ */
id: number; id: number;
/** /**
* Whether this is an ad-hoc action (not from pack installation) * Whether this is an ad-hoc action (not from pack installation)
*/ */
is_adhoc: boolean; is_adhoc: boolean;
/** /**
* Human-readable label * Human-readable label
*/ */
label: string; label: string;
/** /**
* Output schema * Output schema
*/ */
out_schema: any | null; out_schema: any | null;
/** /**
* Pack ID * Pack ID
*/ */
pack: number; pack: number;
/** /**
* Pack reference * Pack reference
*/ */
pack_ref: string; pack_ref: string;
/** /**
* Parameter schema (StackStorm-style with inline required/secret) * Parameter schema (StackStorm-style with inline required/secret)
*/ */
param_schema: any | null; param_schema: any | null;
/** /**
* Unique reference identifier * Unique reference identifier
*/ */
ref: string; ref: string;
/** /**
* Runtime ID * Runtime ID
*/ */
runtime?: number | null; runtime?: number | null;
/** /**
* Semver version constraint for the runtime (e.g., ">=3.12", ">=3.12,<4.0", "~18.0") * Semver version constraint for the runtime (e.g., ">=3.12", ">=3.12,<4.0", "~18.0")
*/ */
runtime_version_constraint?: string | null; runtime_version_constraint?: string | null;
/** /**
* Last update timestamp * Last update timestamp
*/ */
updated: string; updated: string;
/** /**
* Workflow definition ID (non-null if this action is a workflow) * Workflow definition ID (non-null if this action is a workflow)
*/ */
workflow_def?: number | null; workflow_def?: number | null;
}; };

View File

@@ -1,53 +1,54 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
/** /**
* Simplified action response (for list endpoints) * Simplified action response (for list endpoints)
*/ */
export type ActionSummary = { export type ActionSummary = {
/** /**
* Creation timestamp * Creation timestamp
*/ */
created: string; created: string;
/** /**
* Action description * Action description
*/ */
description: string; description: string;
/** /**
* Entry point * Entry point
*/ */
entrypoint: string; entrypoint: string;
/** /**
* Action ID * Action ID
*/ */
id: number; id: number;
/** /**
* Human-readable label * Human-readable label
*/ */
label: string; label: string;
/** /**
* Pack reference * Pack reference
*/ */
pack_ref: string; pack_ref: string;
/** /**
* Unique reference identifier * Unique reference identifier
*/ */
ref: string; ref: string;
/** /**
* Runtime ID * Runtime ID
*/ */
runtime?: number | null; runtime?: number | null;
/** /**
* Semver version constraint for the runtime * Semver version constraint for the runtime
*/ */
runtime_version_constraint?: string | null; runtime_version_constraint?: string | null;
/** /**
* Last update timestamp * Last update timestamp
*/ */
updated: string; updated: string;
/** /**
* Workflow definition ID (non-null if this action is a workflow) * Workflow definition ID (non-null if this action is a workflow)
*/ */
workflow_def?: number | null; workflow_def?: number | null;
}; };

View File

@@ -6,73 +6,74 @@
* Standard API response wrapper * Standard API response wrapper
*/ */
export type ApiResponse_ActionResponse = { export type ApiResponse_ActionResponse = {
/**
* Response DTO for action information
*/
data: {
/** /**
* Creation timestamp * Response DTO for action information
*/ */
created: string; data: {
/**
* Creation timestamp
*/
created: string;
/**
* Action description
*/
description: string;
/**
* Entry point
*/
entrypoint: string;
/**
* Action ID
*/
id: number;
/**
* Whether this is an ad-hoc action (not from pack installation)
*/
is_adhoc: boolean;
/**
* Human-readable label
*/
label: string;
/**
* Output schema
*/
out_schema: any | null;
/**
* Pack ID
*/
pack: number;
/**
* Pack reference
*/
pack_ref: string;
/**
* Parameter schema (StackStorm-style with inline required/secret)
*/
param_schema: any | null;
/**
* Unique reference identifier
*/
ref: string;
/**
* Runtime ID
*/
runtime?: number | null;
/**
* Semver version constraint for the runtime (e.g., ">=3.12", ">=3.12,<4.0", "~18.0")
*/
runtime_version_constraint?: string | null;
/**
* Last update timestamp
*/
updated: string;
/**
* Workflow definition ID (non-null if this action is a workflow)
*/
workflow_def?: number | null;
};
/** /**
* Action description * Optional message
*/ */
description: string; message?: string | null;
/**
* Entry point
*/
entrypoint: string;
/**
* Action ID
*/
id: number;
/**
* Whether this is an ad-hoc action (not from pack installation)
*/
is_adhoc: boolean;
/**
* Human-readable label
*/
label: string;
/**
* Output schema
*/
out_schema: any | null;
/**
* Pack ID
*/
pack: number;
/**
* Pack reference
*/
pack_ref: string;
/**
* Parameter schema (StackStorm-style with inline required/secret)
*/
param_schema: any | null;
/**
* Unique reference identifier
*/
ref: string;
/**
* Runtime ID
*/
runtime?: number | null;
/**
* Semver version constraint for the runtime (e.g., ">=3.12", ">=3.12,<4.0", "~18.0")
*/
runtime_version_constraint?: string | null;
/**
* Last update timestamp
*/
updated: string;
/**
* Workflow definition ID (non-null if this action is a workflow)
*/
workflow_def?: number | null;
};
/**
* Optional message
*/
message?: string | null;
}; };

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
/** /**
* Standard API response wrapper * Standard API response wrapper
*/ */

View File

@@ -2,88 +2,76 @@
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */ /* eslint-disable */
import type { ExecutionStatus } from "./ExecutionStatus"; import type { ExecutionStatus } from './ExecutionStatus';
/** /**
* Standard API response wrapper * Standard API response wrapper
*/ */
export type ApiResponse_ExecutionResponse = { export type ApiResponse_ExecutionResponse = {
/**
* Response DTO for execution information
*/
data: {
/** /**
* Action ID (optional, may be null for ad-hoc executions) * Response DTO for execution information
*/ */
action?: number | null; data: {
/**
* Action ID (optional, may be null for ad-hoc executions)
*/
action?: number | null;
/**
* Action reference
*/
action_ref: string;
/**
* Execution configuration/parameters
*/
config: Record<string, any>;
/**
* Creation timestamp
*/
created: string;
/**
* Enforcement ID (rule enforcement that triggered this)
*/
enforcement?: number | null;
/**
* Identity ID that initiated this execution
*/
executor?: number | null;
/**
* Execution ID
*/
id: number;
/**
* Parent execution ID (for nested/child executions)
*/
parent?: number | null;
/**
* Execution result/output
*/
result: Record<string, any>;
/**
* When the execution actually started running (worker picked it up).
* Null if the execution hasn't started running yet.
*/
started_at?: string | null;
/**
* Execution status
*/
status: ExecutionStatus;
/**
* Last update timestamp
*/
updated: string;
/**
* Worker ID currently assigned to this execution
*/
worker?: number | null;
/**
* Workflow task metadata (only populated for workflow task executions)
*/
workflow_task?: any | null;
};
/** /**
* Action reference * Optional message
*/ */
action_ref: string; message?: string | null;
/**
* Execution configuration/parameters
*/
config: Record<string, any>;
/**
* Creation timestamp
*/
created: string;
/**
* Enforcement ID (rule enforcement that triggered this)
*/
enforcement?: number | null;
/**
* Identity ID that initiated this execution
*/
executor?: number | null;
/**
* Execution ID
*/
id: number;
/**
* Parent execution ID (for nested/child executions)
*/
parent?: number | null;
/**
* Worker ID currently assigned to this execution
*/
worker?: number | null;
/**
* Execution result/output
*/
result: Record<string, any>;
/**
* When the execution actually started running (worker picked it up).
* Null if the execution hasn't started running yet.
*/
started_at?: string | null;
/**
* Execution status
*/
status: ExecutionStatus;
/**
* Last update timestamp
*/
updated: string;
/**
* Workflow task metadata (only populated for workflow task executions)
*/
workflow_task?: {
workflow_execution: number;
task_name: string;
task_index?: number | null;
task_batch?: number | null;
retry_count: number;
max_retries: number;
next_retry_at?: string | null;
timeout_seconds?: number | null;
timed_out: boolean;
duration_ms?: number | null;
started_at?: string | null;
completed_at?: string | null;
} | null;
};
/**
* Optional message
*/
message?: string | null;
}; };

View File

@@ -0,0 +1,21 @@
/* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { Value } from './Value';
/**
* Standard API response wrapper
*/
export type ApiResponse_IdentitySummary = {
data: {
attributes: Value;
display_name?: string | null;
id: number;
login: string;
};
/**
* Optional message
*/
message?: string | null;
};

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
import type { i64 } from './i64'; import type { i64 } from './i64';
import type { OwnerType } from './OwnerType'; import type { OwnerType } from './OwnerType';
/** /**
@@ -61,9 +61,9 @@ export type ApiResponse_KeyResponse = {
*/ */
updated: string; updated: string;
/** /**
* The secret value (decrypted if encrypted) * The secret value (decrypted if encrypted). Can be a string, object, array, number, or boolean.
*/ */
value: string; value: any;
}; };
/** /**
* Optional message * Optional message

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
import type { PackResponse } from './PackResponse'; import type { PackResponse } from './PackResponse';
import type { PackTestResult } from './PackTestResult'; import type { PackTestResult } from './PackTestResult';
/** /**

View File

@@ -0,0 +1,21 @@
/* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
/**
* Standard API response wrapper
*/
export type ApiResponse_PermissionAssignmentResponse = {
data: {
created: string;
id: number;
identity_id: number;
permission_set_id: number;
permission_set_ref: string;
};
/**
* Optional message
*/
message?: string | null;
};

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
/** /**
* Standard API response wrapper * Standard API response wrapper
*/ */

View File

@@ -0,0 +1,30 @@
/* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
/**
* Standard API response wrapper
*/
export type ApiResponse_RuntimeResponse = {
/**
* Full runtime response.
*/
data: {
created: string;
description?: string | null;
distributions: Record<string, any>;
execution_config: Record<string, any>;
id: number;
installation: any | null;
name: string;
pack?: number | null;
pack_ref?: string | null;
ref: string;
updated: string;
};
/**
* Optional message
*/
message?: string | null;
};

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
/** /**
* Standard API response wrapper * Standard API response wrapper
*/ */

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
import type { UserInfo } from './UserInfo'; import type { UserInfo } from './UserInfo';
/** /**
* Standard API response wrapper * Standard API response wrapper

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
/** /**
* Standard API response wrapper * Standard API response wrapper
*/ */

View File

@@ -68,3 +68,4 @@ export type ApiResponse_WorkflowResponse = {
*/ */
message?: string | null; message?: string | null;
}; };

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
/** /**
* Change password request * Change password request
*/ */

View File

@@ -0,0 +1,12 @@
/* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { Value } from './Value';
export type CreateIdentityRequest = {
attributes?: Value;
display_name?: string | null;
login: string;
password?: string | null;
};

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
import type { i64 } from './i64'; import type { i64 } from './i64';
import type { OwnerType } from './OwnerType'; import type { OwnerType } from './OwnerType';
/** /**
@@ -9,7 +9,7 @@ import type { OwnerType } from './OwnerType';
*/ */
export type CreateKeyRequest = { export type CreateKeyRequest = {
/** /**
* Whether to encrypt the value (recommended: true) * Whether to encrypt the value at rest (default: false; use --encrypt / -e from CLI)
*/ */
encrypted?: boolean; encrypted?: boolean;
/** /**
@@ -45,8 +45,8 @@ export type CreateKeyRequest = {
*/ */
ref: string; ref: string;
/** /**
* The secret value to store * The secret value to store. Can be a string, object, array, number, or boolean.
*/ */
value: string; value: any;
}; };

View File

@@ -0,0 +1,10 @@
/* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type CreatePermissionAssignmentRequest = {
identity_id?: number | null;
identity_login?: string | null;
permission_set_ref: string;
};

View File

@@ -0,0 +1,38 @@
/* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
/**
* Request DTO for creating a runtime.
*/
export type CreateRuntimeRequest = {
/**
* Optional human-readable description
*/
description?: string | null;
/**
* Distribution metadata used for verification and platform support
*/
distributions?: Record<string, any>;
/**
* Runtime execution configuration
*/
execution_config?: Record<string, any>;
/**
* Optional installation metadata
*/
installation?: any | null;
/**
* Display name
*/
name: string;
/**
* Optional pack reference this runtime belongs to
*/
pack_ref?: string | null;
/**
* Unique reference identifier (e.g. "core.python", "core.nodejs")
*/
ref: string;
};

View File

@@ -43,3 +43,4 @@ export type CreateWorkflowRequest = {
*/ */
version: string; version: string;
}; };

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
/** /**
* Current user response * Current user response
*/ */

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
export enum EnforcementCondition { export enum EnforcementCondition {
ANY = 'any', ANY = 'any',
ALL = 'all', ALL = 'all',

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
export enum EnforcementStatus { export enum EnforcementStatus {
CREATED = 'created', CREATED = 'created',
PROCESSED = 'processed', PROCESSED = 'processed',

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
import type { EnforcementCondition } from './EnforcementCondition'; import type { EnforcementCondition } from './EnforcementCondition';
import type { EnforcementStatus } from './EnforcementStatus'; import type { EnforcementStatus } from './EnforcementStatus';
import type { i64 } from './i64'; import type { i64 } from './i64';

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
import type { i64 } from './i64'; import type { i64 } from './i64';
/** /**
* Summary event response for list views * Summary event response for list views

View File

@@ -2,80 +2,67 @@
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */ /* eslint-disable */
import type { ExecutionStatus } from "./ExecutionStatus"; import type { ExecutionStatus } from './ExecutionStatus';
/** /**
* Response DTO for execution information * Response DTO for execution information
*/ */
export type ExecutionResponse = { export type ExecutionResponse = {
/** /**
* Action ID (optional, may be null for ad-hoc executions) * Action ID (optional, may be null for ad-hoc executions)
*/ */
action?: number | null; action?: number | null;
/** /**
* Action reference * Action reference
*/ */
action_ref: string; action_ref: string;
/** /**
* Execution configuration/parameters * Execution configuration/parameters
*/ */
config: Record<string, any>; config: Record<string, any>;
/** /**
* Creation timestamp * Creation timestamp
*/ */
created: string; created: string;
/** /**
* Enforcement ID (rule enforcement that triggered this) * Enforcement ID (rule enforcement that triggered this)
*/ */
enforcement?: number | null; enforcement?: number | null;
/** /**
* Identity ID that initiated this execution * Identity ID that initiated this execution
*/ */
executor?: number | null; executor?: number | null;
/** /**
* Execution ID * Execution ID
*/ */
id: number; id: number;
/** /**
* Parent execution ID (for nested/child executions) * Parent execution ID (for nested/child executions)
*/ */
parent?: number | null; parent?: number | null;
/** /**
* Worker ID currently assigned to this execution * Execution result/output
*/ */
worker?: number | null; result: Record<string, any>;
/** /**
* Execution result/output * When the execution actually started running (worker picked it up).
*/ * Null if the execution hasn't started running yet.
result: Record<string, any>; */
/**
* When the execution actually started running (worker picked it up).
* Null if the execution hasn't started running yet.
*/
started_at?: string | null;
/**
* Execution status
*/
status: ExecutionStatus;
/**
* Last update timestamp
*/
updated: string;
/**
* Workflow task metadata (only populated for workflow task executions)
*/
workflow_task?: {
workflow_execution: number;
task_name: string;
triggered_by?: string | null;
task_index?: number | null;
task_batch?: number | null;
retry_count: number;
max_retries: number;
next_retry_at?: string | null;
timeout_seconds?: number | null;
timed_out: boolean;
duration_ms?: number | null;
started_at?: string | null; started_at?: string | null;
completed_at?: string | null; /**
} | null; * Execution status
*/
status: ExecutionStatus;
/**
* Last update timestamp
*/
updated: string;
/**
* Worker ID currently assigned to this execution
*/
worker?: number | null;
/**
* Workflow task metadata (only populated for workflow task executions)
*/
workflow_task?: any | null;
}; };

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
export enum ExecutionStatus { export enum ExecutionStatus {
REQUESTED = 'requested', REQUESTED = 'requested',
SCHEDULING = 'scheduling', SCHEDULING = 'scheduling',

View File

@@ -1,69 +1,56 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
import type { ExecutionStatus } from "./ExecutionStatus"; import type { ExecutionStatus } from './ExecutionStatus';
/** /**
* Simplified execution response (for list endpoints) * Simplified execution response (for list endpoints)
*/ */
export type ExecutionSummary = { export type ExecutionSummary = {
/** /**
* Action reference * Action reference
*/ */
action_ref: string; action_ref: string;
/** /**
* Creation timestamp * Creation timestamp
*/ */
created: string; created: string;
/** /**
* Enforcement ID * Enforcement ID
*/ */
enforcement?: number | null; enforcement?: number | null;
/** /**
* Execution ID * Execution ID
*/ */
id: number; id: number;
/** /**
* Parent execution ID * Parent execution ID
*/ */
parent?: number | null; parent?: number | null;
/** /**
* Rule reference (if triggered by a rule) * Rule reference (if triggered by a rule)
*/ */
rule_ref?: string | null; rule_ref?: string | null;
/** /**
* Execution status * When the execution actually started running (worker picked it up).
*/ * Null if the execution hasn't started running yet.
status: ExecutionStatus; */
/**
* When the execution actually started running (worker picked it up).
* Null if the execution hasn't started running yet.
*/
started_at?: string | null;
/**
* Trigger reference (if triggered by a trigger)
*/
trigger_ref?: string | null;
/**
* Last update timestamp
*/
updated: string;
/**
* Workflow task metadata (only populated for workflow task executions)
*/
workflow_task?: {
workflow_execution: number;
task_name: string;
triggered_by?: string | null;
task_index?: number | null;
task_batch?: number | null;
retry_count: number;
max_retries: number;
next_retry_at?: string | null;
timeout_seconds?: number | null;
timed_out: boolean;
duration_ms?: number | null;
started_at?: string | null; started_at?: string | null;
completed_at?: string | null; /**
} | null; * Execution status
*/
status: ExecutionStatus;
/**
* Trigger reference (if triggered by a trigger)
*/
trigger_ref?: string | null;
/**
* Last update timestamp
*/
updated: string;
/**
* Workflow task metadata (only populated for workflow task executions)
*/
workflow_task?: any | null;
}; };

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
/** /**
* Health check response * Health check response
*/ */

View File

@@ -0,0 +1,12 @@
/* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { Value } from './Value';
export type IdentitySummary = {
attributes: Value;
display_name?: string | null;
id: number;
login: string;
};

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
export enum InquiryStatus { export enum InquiryStatus {
PENDING = 'pending', PENDING = 'pending',
RESPONDED = 'responded', RESPONDED = 'responded',

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
import type { i64 } from './i64'; import type { i64 } from './i64';
import type { InquiryStatus } from './InquiryStatus'; import type { InquiryStatus } from './InquiryStatus';
/** /**

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
/** /**
* Request DTO for installing a pack from remote source * Request DTO for installing a pack from remote source
*/ */

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
import type { i64 } from './i64'; import type { i64 } from './i64';
import type { OwnerType } from './OwnerType'; import type { OwnerType } from './OwnerType';
/** /**
@@ -57,8 +57,8 @@ export type KeyResponse = {
*/ */
updated: string; updated: string;
/** /**
* The secret value (decrypted if encrypted) * The secret value (decrypted if encrypted). Can be a string, object, array, number, or boolean.
*/ */
value: string; value: any;
}; };

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
import type { i64 } from './i64'; import type { i64 } from './i64';
import type { OwnerType } from './OwnerType'; import type { OwnerType } from './OwnerType';
/** /**

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
/** /**
* Login request * Login request
*/ */

View File

@@ -0,0 +1,20 @@
/* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { Value } from './Value';
/**
* Explicit patch operation for nullable JSON fields.
*/
export type NullableJsonPatch = ({
op: NullableJsonPatch.op;
value: Value;
} | {
op: NullableJsonPatch.op;
});
export namespace NullableJsonPatch {
export enum op {
SET = 'set',
}
}

View File

@@ -0,0 +1,19 @@
/* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
/**
* Explicit patch operation for nullable string fields.
*/
export type NullableStringPatch = ({
op: NullableStringPatch.op;
value: string;
} | {
op: NullableStringPatch.op;
});
export namespace NullableStringPatch {
export enum op {
SET = 'set',
}
}

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
export enum OwnerType { export enum OwnerType {
SYSTEM = 'system', SYSTEM = 'system',
IDENTITY = 'identity', IDENTITY = 'identity',

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
import type { PackResponse } from './PackResponse'; import type { PackResponse } from './PackResponse';
import type { PackTestResult } from './PackTestResult'; import type { PackTestResult } from './PackTestResult';
/** /**

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
/** /**
* Simplified pack response (for list endpoints) * Simplified pack response (for list endpoints)
*/ */

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
import type { i64 } from './i64'; import type { i64 } from './i64';
import type { Value } from './Value'; import type { Value } from './Value';
/** /**

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
import type { TestSuiteResult } from './TestSuiteResult'; import type { TestSuiteResult } from './TestSuiteResult';
/** /**
* Pack test result structure (not from DB, used for test execution) * Pack test result structure (not from DB, used for test execution)

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
import type { i64 } from './i64'; import type { i64 } from './i64';
/** /**
* Pack test summary view * Pack test summary view

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
import type { WorkflowSyncResult } from './WorkflowSyncResult'; import type { WorkflowSyncResult } from './WorkflowSyncResult';
/** /**
* Response for pack workflow sync operation * Response for pack workflow sync operation

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
/** /**
* Response for pack workflow validation operation * Response for pack workflow validation operation
*/ */

View File

@@ -1,63 +1,64 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
import type { PaginationMeta } from "./PaginationMeta"; import type { PaginationMeta } from './PaginationMeta';
/** /**
* Paginated response wrapper * Paginated response wrapper
*/ */
export type PaginatedResponse_ActionSummary = { export type PaginatedResponse_ActionSummary = {
/**
* The data items
*/
data: Array<{
/** /**
* Creation timestamp * The data items
*/ */
created: string; data: Array<{
/**
* Creation timestamp
*/
created: string;
/**
* Action description
*/
description: string;
/**
* Entry point
*/
entrypoint: string;
/**
* Action ID
*/
id: number;
/**
* Human-readable label
*/
label: string;
/**
* Pack reference
*/
pack_ref: string;
/**
* Unique reference identifier
*/
ref: string;
/**
* Runtime ID
*/
runtime?: number | null;
/**
* Semver version constraint for the runtime
*/
runtime_version_constraint?: string | null;
/**
* Last update timestamp
*/
updated: string;
/**
* Workflow definition ID (non-null if this action is a workflow)
*/
workflow_def?: number | null;
}>;
/** /**
* Action description * Pagination metadata
*/ */
description: string; pagination: PaginationMeta;
/**
* Entry point
*/
entrypoint: string;
/**
* Action ID
*/
id: number;
/**
* Human-readable label
*/
label: string;
/**
* Pack reference
*/
pack_ref: string;
/**
* Unique reference identifier
*/
ref: string;
/**
* Runtime ID
*/
runtime?: number | null;
/**
* Semver version constraint for the runtime
*/
runtime_version_constraint?: string | null;
/**
* Last update timestamp
*/
updated: string;
/**
* Workflow definition ID (non-null if this action is a workflow)
*/
workflow_def?: number | null;
}>;
/**
* Pagination metadata
*/
pagination: PaginationMeta;
}; };

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
import type { EnforcementCondition } from './EnforcementCondition'; import type { EnforcementCondition } from './EnforcementCondition';
import type { EnforcementStatus } from './EnforcementStatus'; import type { EnforcementStatus } from './EnforcementStatus';
import type { i64 } from './i64'; import type { i64 } from './i64';

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
import type { i64 } from './i64'; import type { i64 } from './i64';
import type { PaginationMeta } from './PaginationMeta'; import type { PaginationMeta } from './PaginationMeta';
/** /**

View File

@@ -1,78 +1,66 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
import type { ExecutionStatus } from "./ExecutionStatus"; import type { ExecutionStatus } from './ExecutionStatus';
import type { PaginationMeta } from "./PaginationMeta"; import type { PaginationMeta } from './PaginationMeta';
/** /**
* Paginated response wrapper * Paginated response wrapper
*/ */
export type PaginatedResponse_ExecutionSummary = { export type PaginatedResponse_ExecutionSummary = {
/**
* The data items
*/
data: Array<{
/** /**
* Action reference * The data items
*/ */
action_ref: string; data: Array<{
/**
* Action reference
*/
action_ref: string;
/**
* Creation timestamp
*/
created: string;
/**
* Enforcement ID
*/
enforcement?: number | null;
/**
* Execution ID
*/
id: number;
/**
* Parent execution ID
*/
parent?: number | null;
/**
* Rule reference (if triggered by a rule)
*/
rule_ref?: string | null;
/**
* When the execution actually started running (worker picked it up).
* Null if the execution hasn't started running yet.
*/
started_at?: string | null;
/**
* Execution status
*/
status: ExecutionStatus;
/**
* Trigger reference (if triggered by a trigger)
*/
trigger_ref?: string | null;
/**
* Last update timestamp
*/
updated: string;
/**
* Workflow task metadata (only populated for workflow task executions)
*/
workflow_task?: any | null;
}>;
/** /**
* Creation timestamp * Pagination metadata
*/ */
created: string; pagination: PaginationMeta;
/**
* Enforcement ID
*/
enforcement?: number | null;
/**
* Execution ID
*/
id: number;
/**
* Parent execution ID
*/
parent?: number | null;
/**
* Rule reference (if triggered by a rule)
*/
rule_ref?: string | null;
/**
* Execution status
*/
status: ExecutionStatus;
/**
* When the execution actually started running (worker picked it up).
* Null if the execution hasn't started running yet.
*/
started_at?: string | null;
/**
* Trigger reference (if triggered by a trigger)
*/
trigger_ref?: string | null;
/**
* Last update timestamp
*/
updated: string;
/**
* Workflow task metadata (only populated for workflow task executions)
*/
workflow_task?: {
workflow_execution: number;
task_name: string;
task_index?: number | null;
task_batch?: number | null;
retry_count: number;
max_retries: number;
next_retry_at?: string | null;
timeout_seconds?: number | null;
timed_out: boolean;
duration_ms?: number | null;
started_at?: string | null;
completed_at?: string | null;
} | null;
}>;
/**
* Pagination metadata
*/
pagination: PaginationMeta;
}; };

View File

@@ -0,0 +1,25 @@
/* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { PaginationMeta } from './PaginationMeta';
import type { Value } from './Value';
/**
* Paginated response wrapper
*/
export type PaginatedResponse_IdentitySummary = {
/**
* The data items
*/
data: Array<{
attributes: Value;
display_name?: string | null;
id: number;
login: string;
}>;
/**
* Pagination metadata
*/
pagination: PaginationMeta;
};

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
import type { i64 } from './i64'; import type { i64 } from './i64';
import type { InquiryStatus } from './InquiryStatus'; import type { InquiryStatus } from './InquiryStatus';
import type { PaginationMeta } from './PaginationMeta'; import type { PaginationMeta } from './PaginationMeta';

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
import type { i64 } from './i64'; import type { i64 } from './i64';
import type { OwnerType } from './OwnerType'; import type { OwnerType } from './OwnerType';
import type { PaginationMeta } from './PaginationMeta'; import type { PaginationMeta } from './PaginationMeta';

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
import type { PaginationMeta } from './PaginationMeta'; import type { PaginationMeta } from './PaginationMeta';
/** /**
* Paginated response wrapper * Paginated response wrapper

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
import type { i64 } from './i64'; import type { i64 } from './i64';
import type { PaginationMeta } from './PaginationMeta'; import type { PaginationMeta } from './PaginationMeta';
/** /**

View File

@@ -0,0 +1,27 @@
/* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { PaginationMeta } from './PaginationMeta';
/**
* Paginated response wrapper
*/
export type PaginatedResponse_RuntimeSummary = {
/**
* The data items
*/
data: Array<{
created: string;
description?: string | null;
id: number;
name: string;
pack_ref?: string | null;
ref: string;
updated: string;
}>;
/**
* Pagination metadata
*/
pagination: PaginationMeta;
};

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
import type { PaginationMeta } from './PaginationMeta'; import type { PaginationMeta } from './PaginationMeta';
/** /**
* Paginated response wrapper * Paginated response wrapper

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
import type { PaginationMeta } from './PaginationMeta'; import type { PaginationMeta } from './PaginationMeta';
/** /**
* Paginated response wrapper * Paginated response wrapper

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
import type { PaginationMeta } from './PaginationMeta'; import type { PaginationMeta } from './PaginationMeta';
/** /**
* Paginated response wrapper * Paginated response wrapper
@@ -53,3 +53,4 @@ export type PaginatedResponse_WorkflowSummary = {
*/ */
pagination: PaginationMeta; pagination: PaginationMeta;
}; };

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
/** /**
* Pagination metadata * Pagination metadata
*/ */

View File

@@ -0,0 +1,12 @@
/* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type PermissionAssignmentResponse = {
created: string;
id: number;
identity_id: number;
permission_set_id: number;
permission_set_ref: string;
};

View File

@@ -0,0 +1,14 @@
/* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { Value } from './Value';
export type PermissionSetSummary = {
description?: string | null;
grants: Value;
id: number;
label?: string | null;
pack_ref?: string | null;
ref: string;
};

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
/** /**
* Response DTO for queue statistics * Response DTO for queue statistics
*/ */

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
/** /**
* Refresh token request * Refresh token request
*/ */

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
/** /**
* Request DTO for registering a pack from local filesystem * Request DTO for registering a pack from local filesystem
*/ */

View File

@@ -1,7 +1,7 @@
/* generated using openapi-typescript-codegen -- do not edit */ /* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */ /* istanbul ignore file */
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */
/** /**
* Register request * Register request
*/ */

View File

@@ -0,0 +1,21 @@
/* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
/**
* Full runtime response.
*/
export type RuntimeResponse = {
created: string;
description?: string | null;
distributions: Record<string, any>;
execution_config: Record<string, any>;
id: number;
installation: any | null;
name: string;
pack?: number | null;
pack_ref?: string | null;
ref: string;
updated: string;
};

Some files were not shown because too many files have changed in this diff Show More