# Shared contracts for the event pipeline system # # Mirrors rustelo_server::nats::pipeline — PipelineConfig, Pipeline, # PipelineTrigger, PipelineStep, MessageTarget. # # Sub-type contracts are in: # pipelines/nats/contracts.ncl — NatsPipeline (pipeline_type = "nats") # pipelines/ci_cd/contracts.ncl — CiCdPipeline (pipeline_type = "ci_cd") # # Validate standalone: # source .env && nickel export --format json site/config/pipelines.ncl # # or with explicit import path: # nickel export --format json --import-path site/nickel site/config/pipelines.ncl # ── Allowed value sets ───────────────────────────────────────────────────────── let PipelineTypes = ["nats", "ci_cd"] in let StepTypes = ["cache_invalidate", "broadcast", "script", "persist_message"] in let TargetTypes = ["user_id", "payload_field"] in let ToastKinds = ["info", "success", "warning", "error"] in # ── Reusable primitive contracts ─────────────────────────────────────────────── let OneOf = fun allowed => std.contract.from_predicate (fun v => std.array.elem v allowed) in let NonEmpty = std.contract.from_predicate (fun s => std.is_string s && std.string.length s > 0) in # ── Contracts ────────────────────────────────────────────────────────────────── { # MessageTarget — selects the target user for a persist_message step. MessageTarget = { type | OneOf TargetTypes | doc "Selector variant: user_id — literal UUID configured in the pipeline payload_field — extract UUID from a JSON field in the payload", value | String | NonEmpty | doc "user_id: literal UUID of the target user" | optional, field | String | NonEmpty | doc "payload_field: JSON field name that contains the user UUID" | optional, .. }, # PipelineStep — one action in the execution chain. # Variant-specific fields are optional; the executor validates # required fields at runtime matching the Rust enum. PipelineStep = { type | OneOf StepTypes | doc "Step variant: cache_invalidate — flush the in-process content cache broadcast — send a WebSocket toast to all clients script — execute a Nu or shell script persist_message — store a message in a user's inbox (requires auth feature)", # ── broadcast ──────────────────────────────────────────────────────────── kind | String | OneOf ToastKinds | doc "broadcast: toast severity — info | success | warning | error" | optional, message | String | NonEmpty | doc "broadcast: toast body shown to connected WebSocket clients" | optional, # ── script ─────────────────────────────────────────────────────────────── path | String | NonEmpty | doc "script: path to script file (.nu → nu, .sh → sh, other → direct exec). Relative paths resolve against SITE_CONTENT_PATH. Script receives PIPELINE_EVENT and PIPELINE_PAYLOAD env vars (plus NATS_SUBJECT / NATS_PAYLOAD aliases for NATS pipelines)." | optional, # ── persist_message ─────────────────────────────────────────────────────── target | MessageTarget | doc "persist_message: user selector" | optional, sender_email | String | NonEmpty | doc "persist_message: sender label shown in the user's inbox" | optional, subject_template | String | NonEmpty | doc "persist_message: message subject; supports {{field}} substitution" | optional, body_template | String | doc "persist_message: body template; defaults to raw payload when omitted" | optional, }, # Pipeline — generic shape shared by all pipeline types. # Use the type-specific contracts (nats/contracts.ncl, ci_cd/contracts.ncl) # for stricter validation of individual files. Pipeline = { pipeline_type | OneOf PipelineTypes | doc "Trigger mechanism: nats — NATS JetStream subject subscription ci_cd — CI/CD event hook (webhook-driven)", name | String | NonEmpty | doc "Human-readable identifier used in structured log output", steps | Array PipelineStep | doc "Ordered actions executed sequentially on each trigger. Step failures are logged and do not abort subsequent steps." | default = [], .. }, # PipelinesConfig — root record, deserialized directly into PipelineConfig. PipelinesConfig = { pipelines | Array Pipeline | doc "Aggregated list of all event pipelines across all trigger types." | default = [], }, }