Replaces separate Url/User/Password inputs on NatsPublish and NatsTrigger with
one Connection input in standard NATS URL form (e.g. nats://user:pass@host:4222,
wss://user:pass@host/). The activity's input description explains the format so
it renders as help text in the Studio property panel.
NatsConnectionCache now parses the connection string, keeps its cache keyed on
the parsed (url, user, password) tuple, and exposes ParseConnectionString for
reuse. NatsTriggerStimulus collapses to (Connection, Stream, Subject); existing
NATS workflows must be republished to re-index with the new stimulus shape.
Url/User/Password are now inputs on NatsPublish and NatsTrigger so authors
configure them in the workflow designer. The stored trigger stimulus carries
the connection info too, so messages from server A only fire workflows
designed to listen on server A. Dropped the AddNats singleton wiring and the
Nats section from appsettings.
A NatsConnectionCache singleton hands out one NatsConnection per unique
(url, user, password) so repeat publishes and each hosted-service consumer
loop reuse the same TCP session.
NatsPublish (CodeActivity) publishes a UTF-8 body to a subject with optional
Nats-Msg-Id dedup and ExpectedStream assertion. NatsTrigger (Trigger<string>)
starts a workflow per message on a specified stream/subject.
A single BackgroundService scans the trigger store for indexed NatsTriggers,
groups by (stream, subject), and runs one durable pull consumer per pair with
Explicit ack, so multiple Elsa instances share the workload at-least-once. A
mediator handler on WorkflowTriggersIndexed refreshes subscriptions when
workflows are published.
Wired via Nats:Url/User/Password (env-var overrides Nats__*, or short
NATS_URL/NATS_USER/NATS_PASSWORD fallbacks). Uses the NATS.Net v2 client so
wss:// works transparently.
Captures everything that took a debug cycle to figure out: server-vs-Studio
version divergence (3.5 vs 3.7), the two competing login stacks and which
one to keep, the admin password-hash trap, Traefik forwarded-headers, the
SPA fallback carving out /elsa/api, SQLite pinning to App_Data, and the
Coolify quirks (git_repository truncation, dockercompose→service, base64
raw compose). Future sessions read this first before touching versions
or auth wiring.