Rustelo/resources/nickel/pipelines/contracts.ncl
Jesús Pérez f1010e9d07
chore: update
2026-07-18 20:16:16 +01:00

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 = [],
},
}