Corral is a single, self-contained application that gives operators deep visibility into a Durabull deployment. Deploy it once, point it at your Redis-backed Durabull environment, and you get live workflow analytics, searchable history, and safe operator actions without running distinct frontend, API, and worker processes.
- Single deployable unit – Next.js App Router with server-rendered UI and API routes in one package.
- Durabull-native insights – live stats, hourly trends, workflow lists, detailed history timelines, and activity summaries.
- Operator toolkit – send signals, resume waiting executions, and continue-as-new (respecting optional read-only mode and role-based auth).
- Config-driven – supply Redis coordinates, queue names, serializer, and auth mode via environment variables at deploy time.
- Observability built-in –
/api/healthzand/api/readyzchecks, structured logging, and metrics sampling utilities.
┌──────────────────────────────┐
│ Next.js (App Router) │
│ ┌───────────┬──────────────┐ │
│ │ UI Pages │ API Routes │ │
│ │ (React) │ (REST/JSON) │ │
│ └─────▲─────┴───────▲──────┘ │
│ │ │ │
│ ┌───┴──────────┐ │ │
│ │ Durabull │◄─┘ │
│ │ Adapter Lib │ │
│ └─────▲────────┘ │
└─────────│────────────────────┘
│
┌───▼──────────────┐
│ Redis + BullMQ │
│ (Durabull data) │
└──────────────────┘
The adapter library configures Durabull once, reuses Redis connections, and exposes high-level functions for:
- Sampling workflow records for dashboards and charts.
- Listing/filtering workflows with SCAN-based pagination.
- Fetching per-workflow history, signals, children, and derived activity summaries.
- Triggering safe actions (resume, continue-as-new, send signal) with read-only and auth checks.
- Node.js 18+ (Next.js target)
- npm
- A reachable Redis instance hosting Durabull data
git clone https://github.com/typescript-workflow/corral.git
cd corral
npm installCopy .env.example to .env and adjust as needed:
DURABULL_REDIS_URL=redis://127.0.0.1:6379
DURABULL_WORKFLOW_QUEUE=durabull:workflow
DURABULL_ACTIVITY_QUEUE=durabull:activity
DURABULL_SERIALIZER=json
DURABULL_PRUNE_AGE=30 days
APP_BASE_URL=http://localhost:3000
APP_AUTH_MODE=none
READ_ONLY_MODE=falseToken auth: set
APP_AUTH_MODE=tokenand provideAPP_AUTH_TOKENas comma-separated entries in the formatrole|role:token(e.g.viewer:reader-token,operator:ops-token). Corral acceptsAuthorization: Bearer,X-API-Key, orcorral_tokencookies.
npm run devVisit http://localhost:3000 to access the dashboard. All pages are server-rendered and backed by live data from the configured Durabull Redis.
npm run build
npm startCorral listens on port 3000 by default (configurable through your hosting platform).
| Variable | Description | Default |
|---|---|---|
DURABULL_REDIS_URL |
Redis connection string used by Durabull storage & queues | redis://127.0.0.1:6379 |
DURABULL_WORKFLOW_QUEUE |
Workflow queue name | durabull:workflow |
DURABULL_ACTIVITY_QUEUE |
Activity queue name | durabull:activity |
DURABULL_SERIALIZER |
Serializer key (json | base64) |
json |
DURABULL_PRUNE_AGE |
Retention window hint for Durabull | 30 days |
APP_BASE_URL |
Optional canonical URL (display only) | — |
APP_AUTH_MODE |
none | token | oidc (OIDC planned) |
none |
APP_AUTH_TOKEN |
Comma-separated token specs (`role | role:token) when token` mode is enabled |
READ_ONLY_MODE |
true disables mutating actions |
false |
- Dashboard – KPIs (started today, 24h throughput, median/p95 duration, failure rate, signal volume, suspected stuck workflows) plus live status counts and recent executions.
- Workflows list – Filter by status, apply cursor-based pagination, and jump to detail views.
- Workflow detail – Timeline of history events, activity attempt aggregation, queued signals, child relationships, and operator actions.
- Actions & signals – Resume waiting workflows, trigger continue-as-new with custom args, or enqueue signals (disabled automatically in read-only mode).
The UI talks to colocated API routes that you can also call programmatically:
GET /api/stats– dashboard metrics snapshot.GET /api/workflows– paginated list with status/class filters.GET /api/workflows/:id– full record, history, signals, activities, and children.GET /api/workflows/:id/signals– queued signals.POST /api/workflows/:id/signals– enqueue a new signal (operator only).POST /api/workflows/:id/actions–resumeorcontinueAsNew(operator only).GET /api/activities?workflowId=...– activity summaries (used by detail view).GET /api/healthz,GET /api/readyz– health/readiness checks.
All responses are JSON; errors conform to { error: string, details?: unknown }.
- Modes:
none(default),token, and placeholderoidc(not yet implemented). - Token RBAC: assign roles (
viewer,operator) per token. Viewer = read-only. Operator can send signals, resume, continue-as-new. - Read-only guard:
READ_ONLY_MODE=truedisables all mutating endpoints regardless of role. - Audit-friendly: Responses include timestamps and Corral logs every action to stdout with status and workflow id.
- Type checking –
npm run typecheck - Linting –
npm run lint - Formatting –
npm run format
The project ships with ESLint (flat config), Prettier, TypeScript strict mode, and devcontainer support.
Corral is a single Next.js app; deploy it anywhere you can run Node.js 18+ or container workloads:
docker build -t corral-app .
docker run -p 3000:3000 --env-file .env corral-appOn serverless platforms (e.g. Vercel, Netlify), make sure outbound TCP to your Redis is allowed. Container platforms (Fly.io, Render, Railway, ECS, Kubernetes) are the easiest route when Redis is private.
- OIDC login + session storage
- Enhanced audit logging (database sink)
- Charting polish (sparkline + failure breakdowns)
- Bulk actions and saved filters
- Historical rollups backed by Durabull prune windows
Issues, ideas, and PRs are welcome. Please open a discussion if you plan substantial changes so we can align on direction.
MIT — see LICENSE.
Built with ❤️ to make running Durabull in production frictionless.