Skip to content
Projects

SELISEdigitalplatforms/blocks-logic has 43 GitHub stars and 1 forks. GitHot measured 0 in 7 days. Last checked 2026-11-10 23:08 UTC. Last push 2026-11-02.

How these counts are measured

Workflow and business-logic engine for SELISE Blocks: workflow nodes, execution services and magic-link flows.

Measured star growth

in 24h
Update delayed
in 7 days
0
in 15 days
Collecting history
in 1 month
Collecting history

Net star changes over overlapping periods, not daily totals. Missing measurements are left blank. Stars measure attention, not software quality.

README.md

Original

Blocks Logic

Blocks Logic is the workflow and automation service of the SELISE <Blocks/> platform: a React (Vite, TypeScript) single-page application with a visual workflow builder, a Genesis-backed ASP.NET Core API, a background Worker that executes workflows and consumers, and a Scheduler.Worker that fires schedules. The SPA is built into server/Api/wwwroot so Kestrel can serve the UI and backend from one host. The logic domain (server/DomainService) covers workflow definition and execution (triggers, nodes, transforms), the template engine, magic links, PDF generation, sequences, geolocation and storage helpers.

Project structure

blocks-logic/
├── client/                         # React + Vite + TypeScript
│   ├── app/                        # Application source
│   │   ├── modules/workflow/       # Visual workflow builder (React Flow canvas, nodes, triggers)
│   │   ├── routes/                 # Route modules
│   │   ├── components/, hooks/, lib/, providers/
│   │   ├── main.tsx, router.tsx
│   │   └── …
│   ├── public/                     # Static assets
│   ├── index.html
│   ├── vite.config.ts              # build.outDir → ../server/Api/wwwroot; `BLOCKS_*` env prefix
│   ├── package.json
│   └── .env.example                # Copy to .env (see below)
├── server/
│   ├── Api/                        # Web host (Kestrel, Genesis, controllers, static SPA)
│   │   ├── Controllers/            # HTTP API (attribute routes; `api` prefix via convention)
│   │   ├── wwwroot/                # Vite output (generated; do not edit by hand)
│   │   ├── Program.cs
│   │   ├── Api.csproj
│   │   └── GlobalApiRoutePrefixConvention.cs
│   ├── Worker/                     # Background worker (message consumers, workflow execution)
│   ├── Scheduler.Worker/           # Scheduler host: Hangfire, schedule registry consumers (ONE replica)
│   ├── DomainService/              # Logic domain: Workflow, TemplateEngine, MagicLink,
│   │                               #   PdfGenerator, Sequence, Geolocation, Messaging, Storage
│   ├── Authentication.DomainService/
│   ├── Captcha.DomainService/
│   ├── Cloud.DomainService/
│   ├── Cloud.LmtService/
│   ├── CloudConfiguration.DomainService/
│   ├── Iam.DomainService/
│   ├── Identifier.DomainService/
│   ├── Mail.DomainService/
│   ├── Mfa.DomainService/
│   ├── Notification.DomainService/
│   ├── XUnitTest/                  # Unit tests
│   ├── Captcha.Driver/, Iam.Driver/, Mfa.Driver/, Mail.Driver/   # Driver-style projects
│   └── Blocks.slnx                 # Solution: Api, domain libraries, Worker, Scheduler.Worker, XUnitTest
├── e2e/                            # Playwright end-to-end tests (see e2e/README.md)
├── scripts/                        # scan.sh and deploy.sh entry points
├── run.sh                          # Build/run helpers (Unix/macOS; see below)
├── run.ps1                         # Same role on Windows (PowerShell; see below)
├── LICENSE
└── README.md

Prerequisites

Local infrastructure

To run Blocks Logic locally, clone blocks-infra and bring up its Docker Compose stack (for example docker compose up -d, using the compose file and options described in that repository). Start that stack before or alongside the API and Worker from this repo so local dependencies (databases, queues, and so on) are available.

How to run

Both run.sh (Bash) and run.ps1 (PowerShell) live at the repo root. They require an option; calling them with no recognized flags prints usage and exits.

Ports: both scripts assume API port 5000. run.sh also uses 4000 for npm run dev when you pass -f (see run.sh). server/Api/Properties/launchSettings.json may differ for IDE launches; use the URL your process prints.

Options (same flags, different invocation)

Option Role
-a, --all Install/build client, sync client/dist → server/Api/wwwroot, then start API, Worker and Scheduler.Worker
-b, --backend Run API only (dotnet run on server/Api/Api.csproj)
-w, --worker Run Worker only (server/Worker/Worker.csproj)
-s, --scheduler Run Scheduler.Worker only (server/Scheduler.Worker/Scheduler.Worker.csproj). Run one at a time: see Scheduler.Worker
-f, --frontend Vite dev server: npm run dev in client/ (run.sh installs dependencies only if node_modules is missing; run.ps1 runs npm install every time)
-k, --kill-port Stop whatever is listening on the API port (5000)
-n, --npm args… Run npm in client/ (e.g. run test, run build)
-tb, -tf, -te, -ta Test shortcuts: backend, frontend, e2e, all (see ./run.sh -h)
-h, --help Show usage

Windows only (run.ps1): -d / --dotnet args… runs dotnet from the repo root (for example restore, build, or test commands).

Unix / macOS (run.sh)

./run.sh -a              # full stack (build + API + Worker + Scheduler.Worker in this shell)
./run.sh -b              # API only (frees port 5000 first)
./run.sh -s              # Scheduler.Worker only
./run.sh -f              # Vite dev server
./run.sh -n run test     # npm in client/

run.sh syncs the built SPA with rsync (dist/ → wwwroot/). For -a, the API, Worker and Scheduler.Worker run as background jobs in the same terminal; Ctrl+C runs the script’s cleanup trap.

Windows (run.ps1)

.\run.ps1 -a             # build + start API, Worker and Scheduler.Worker in separate windows
.\run.ps1 -b             # API only (restore + free port 5000 first)
.\run.ps1 -f             # Vite dev server
.\run.ps1 -n run test    # npm in client/
.\run.ps1 -d test server/XUnitTest/XUnitTest.csproj

run.ps1 syncs dist → wwwroot with robocopy. It runs dotnet restore on the Api, Worker and Scheduler.Worker projects before -b, -w, -s and -a. With -a, three extra PowerShell windows open (API, Worker, Scheduler.Worker); press Enter in the original window to stop those processes.

Without the scripts

If the client is already built into wwwroot:

dotnet run --project server/Api/Api.csproj

Client environment (BLOCKS_*)

Vite exposes env vars prefixed with BLOCKS_ (see client/vite.config.ts). Copy client/.env.example → client/.env and set values as needed:

  • BLOCKS_API_BASE_URL: external backend target for Vite's local /api proxy. Browser calls to Logic use the page origin.
  • BLOCKS_X_BLOCKS_KEY: Genesis / Blocks project key when your environment requires it.
  • BLOCKS_IAM_BASE_URL: IAM base URL for the OIDC sign-in flow.
  • BLOCKS_OIDC_CLIENT_ID: OIDC client id used by the sign-in flow.

Rebuild the client (npm run build in client/ or ./run.sh -a / .\run.ps1 -a) after changing env for production bundles.

Production / publish

Build the client, then publish the API (ensure wwwroot contains the built SPA if you want the UI in the output):

(cd client && npm install && npm run build)
dotnet publish server/Api/Api.csproj -c Release -o ./publish

No Node process is required on the server at runtime.

Tests

Run from the repository root:

# backend unit tests (xUnit)
dotnet test server/XUnitTest/XUnitTest.csproj

# frontend unit tests (Vitest)
npm --prefix client run test

# end-to-end tests (Playwright); needs a reachable app and e2e/.env.e2e,
# see e2e/README.md for setup and target modes
npm --prefix e2e run test

Coverage:

dotnet test server/XUnitTest/XUnitTest.csproj --collect:"XPlat Code Coverage"
npm --prefix client run test -- --coverage

Scheduler.Worker

server/Scheduler.Worker (service and image blocks-logic-scheduler-worker, Dockerfile.scheduler) is the only process that fires schedules. It hosts the in-memory Hangfire server, rebuilds the recurring jobs from Mongo at startup, and consumes the schedule registry queue (blcoks_logic_scheduler_job_registry_listener). The Api and Worker send registry events to it when a schedule changes; the Worker still consumes the workflow schedule trigger (SchedulerTriggerConsumer).

  • Run exactly one replica. Hangfire storage is in memory, so every replica would fire every schedule. Deploy it with one replica, the Recreate strategy and no autoscaling, and as a single systemd unit. The Worker can run any number of replicas.
  • Startup. The reseed is tried 5 times (2, 4, 8 and 16 s apart). If all fail, the process exits with code 1 so Kubernetes or systemd restarts it.
  • Missed ticks are not replayed. Occurrences that fall while the process is down are skipped.
  • Releases. CI builds and rolls out Scheduler.Worker before the Worker; the Worker's GitOps update waits for it. To roll back, redeploy the previous Worker image first, then scale Scheduler.Worker to 0.

Scanning and deployment

  • scripts/scan.sh is the security scan entry point (SAST, SCA and secret scanning). It is intentionally not tracked in git; internal environments provide it.
  • scripts/deploy.sh is the maintainer deploy script for a systemd host: it checks out the latest inception, builds the client, publishes the Api and Worker projects, and installs and restarts their systemd services.

API and routing

  • Controllers live under server/Api/Controllers/ (workflow, template, notification, mail, storage, people, project, language, monitor, migration, deployment, health, captcha, MFA). Route templates omit the api segment in code; GlobalApiRoutePrefixConvention in Program.cs adds the api prefix for attribute-routed controllers.
  • /api is reserved for the HTTP API in the integrated setup; keep client-side routes from colliding with API paths.

Contributing and security

Database placement (Genesis 4.2.2)

API, Worker, and MailBoxSyncService use the published Genesis 4.2.2 package. Runtime access follows each tenant's stored DbConnectionString and DBName; environment-to-connection selection belongs to OS.

The scheduler discovers enabled tenants from main's configured root database and scans their stored connections. It logs each failed tenant and continues scanning healthy tenants; a root registry failure propagates. Job registration and queue publishing retain the scheduled tenant ID. Notification configuration and notification writes resolve their database per operation, including when repositories are singletons. Identifier project/membership metadata remains on main/root; managed-service reads retain their tenant/impersonation semantics. Mailbox, workflow, proxy, and monitoring stores retain their existing ownership.

Notification listing, subscription-filter queries, and read-status updates cover both the current tenant database and main/root, where impersonated writes can land. An unresolved placement fails the read rather than returning an incomplete page. Mailbox sync skips a tenant whose inbound configuration database is unavailable and continues with the other tenants in that polling cycle.

Routing regression tests include scheduler connection selection/failure isolation, scheduled-message context, and concurrent notification writes and refreshed placement using the real Genesis provider. Local integration tests use disposable databases; run a compatible local MongoDB (4.4 or newer for the currently resolved driver), then:

dotnet test server/XUnitTest/XUnitTest.csproj -c Release

The new routing fixture defaults to localhost:27017. Set BLOCKS_ROUTING_TEST_MONGO_PORT to use another local test port. It never accepts a remote server or deployed credentials. These tests do not establish deployed cluster connectivity. The latest dev baseline also has eight unrelated failing ActionProxyNodeTests; those failures were reproduced before these changes.

Deploy every API, worker, scheduler host and mailbox process before enabling split placement in OS. Keep one main/root registry. Existing tenant migration, missed Redis refresh recovery and cross-cluster cutover remain separate work.

License

See LICENSE.

Explore related projects