127 lines
5.4 KiB
Text
127 lines
5.4 KiB
Text
# 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 = [],
|
|
},
|
|
}
|