Task dashboard workflow (snapshot + SSE)
This document describes the dashboard API/runtime in alakai (backend) built on top of Redis task tracking.
The Next.js UI lives in the separate alakai-dashboard repository.
Scope
- Snapshot reads for current task status list views.
- Realtime no-polling updates via SSE.
- Available project list endpoint for dashboard filters.
- Mandatory Google-authenticated access to dashboard routes.
- Optional strict visibility filtering based on creator/responsible users.
Runtime topology
Dashboard runtime is always active:
RedisTaskDashboardReadServicereads projected latest-state task records from Redis.RedisTaskTrackingStreamTailertailstask-events:v1(XREAD, blocking).TaskDashboardUpdatesHubkeeps bounded replay and fanouts updates to subscribers.- HTTP routes expose:
GET /dashboard/projectsGET /dashboard/tasksGET /dashboard/tasks/stream(text/event-stream)
Redis Stream (task-events:v1)
│
├─> RedisTaskStatusProjector -> Redis latest-state hashes + project ZSET
│
└─> RedisTaskTrackingStreamTailer -> TaskDashboardUpdatesHub -> SSE clients
Redis read model used by dashboard
- Per execution hash:
task-tracking:execution:{executionId} - Per project ordered index:
task-tracking:project:{project}:executions- score:
occurredAttimestamp (ms) - value:
executionId
- score:
Available projects endpoint
GET /dashboard/projects
- Returns configured projects (each with their applications) for dashboard filtering:
{
"items": [
{
"project": "rukipay",
"displayName": "Rukipay",
"applications": [
{ "app": "rukipay-backend", "repo": "houlak/rukipay-backend" }
]
}
]
}
- Source of truth is the projects workflow config loaded at runtime (S3 with file fallback if configured that way).
- Note: task events (the
/dashboard/taskssnapshot below) still key theirprojectfield byowner/repo, not by the project slug — the two endpoints expose different identifiers. - Requires authenticated viewer (returns
401 dashboard_unauthorizedwhen missing/invalid auth).
Snapshot endpoint
GET /dashboard/tasks
Query params:
project(recommended for practical queries)statuses(comma-separated or repeated array values)cursor(opaque cursor for pagination)limitauthToken(optional Google ID token fallback;Authorization: Bearerpreferred)
Response:
{
"items": [
{
"executionId": "...",
"taskName": "...",
"status": "in_progress|success|error",
"project": "owner/repo",
"occurredAt": "ISO-8601",
"flow": "...",
"actor": { "provider": "slack|github", "id": "..." },
"prLinks": [],
"visibility": { "responsibleUsers": [] },
"lastEventId": "<redis-stream-id>"
}
],
"nextCursor": "..."
}
Realtime endpoint
GET /dashboard/tasks/stream
- Content type:
text/event-stream - Supports resume via:
Last-Event-IDheadercursorquery
- Supports
authTokenquery fallback for EventSource/browser environments where customAuthorizationheaders are not practical.
Event types:
task_status_updatedsnapshot_refresh_requiredkeepalive
If a cursor cannot be replayed from the in-memory replay window, the server emits snapshot_refresh_required and the client should reload snapshot.
Auth boundary (mandatory Google auth)
Dashboard routes require an authenticated viewer.
Token inputs:
- Preferred:
Authorization: Bearer <google_id_token> - SSE/browser fallback:
authTokenquery param
Identity resolution:
google:{email}when verified email is availablegoogle-sub:{sub}fallback
When identity cannot be resolved, routes return:
- HTTP
401 error: "dashboard_unauthorized"
Visibility model
Visibility behavior is controlled by TASK_DASHBOARD_ENFORCE_VISIBILITY:
false(default): all tasks are visible to authenticated viewers.true: access allowed only when:- Viewer identity matches task creator (
{provider}:{id}), or - Viewer identity appears in
visibility.responsibleUsers.
- Viewer identity matches task creator (
Operational guidance
Required env
TASK_TRACKING_REDIS_URLTASK_DASHBOARD_GOOGLE_CLIENT_IDS
Optional env
TASK_DASHBOARD_HEARTBEAT_MS(default15000)TASK_DASHBOARD_REPLAY_LIMIT(default200)TASK_DASHBOARD_SNAPSHOT_DEFAULT_LIMIT(default50)TASK_DASHBOARD_SNAPSHOT_MAX_LIMIT(default200)TASK_DASHBOARD_ENFORCE_VISIBILITY(true|false, defaultfalse)
Local run
- Start backend:
yarn dev - Start dashboard UI in separate repo:
cd ~/houlak_projects/alakai-dashboard && yarn dev - Open
http://localhost:5173
Build checks
- Backend:
yarn build - Dashboard (separate repo):
cd ~/houlak_projects/alakai-dashboard && yarn build