DashboardService¶
Target
This page describes intended behaviour or structure. No implementation is claimed unless a section is explicitly marked Current implementation or Evidence.
| Bounded context | BC-21 Operations |
| Platform / plane | Observability / Trust & Operations |
| Deployment granularity | module of host · host ObservabilityHost |
| Status | target · ConnectSoft.Factory.Observability.Operations |
| Built from | connectsoft-microservice · libraries: connectsoft-extensions-saas-abstractions, connectsoft-extensions-messaging-model, connectsoft-extensions-persistence-model-nhibernate, connectsoft-extensions-query-model, connectsoft-extensions-service-model-signal-r |
| Decisions | ADR-0014, ADR-0018 |
| Traceability | FR-10 FUX-04 FUX-07 FUX-08 NFR-10 NFR-07 XL-06 XL-12 XL-16 |
Purpose and responsibilities¶
DashboardService builds the read models an operator, reviewer or requester looks at: the run timeline (the original design's §51 trace tree as rows — steps, attempts, phases, model receipts, tool receipts, context snapshots, approvals, decisions and usage by status) and the overviews per tenant, project, agent, workflow, tool and model over a window (task success, agent success, cost per task, latency per task, tokens per task, tool failure rate, model fallback rate, human intervention rate, sandbox failures, context retrieval quality, evaluation score). It streams projection updates to the Studio BFF so a run page moves without polling.
It is a projection, by design and by rule: Run Control's journal is the truth of a run, the producers' receipts are the truth of each call, and the projection is rebuilt from them whenever it disagrees. It absorbs AgentTelemetryService and the June-2026 DashboardService into one projection module.
Context and boundaries¶
flowchart LR
S["DashboardService"]
StudioBff["StudioBff"] -->|sync-http| S
SloService["SloService"] -->|event| S
S -->|grpc| RunControlService["RunControlService"]
S -->|sync-http| ext_otel_backend["ext-otel-backend"]
S -. "RunProjectionUpdated" .-> E_RunProjectionUpdated(("event"))
S -. "OperationsDigestProduced" .-> E_OperationsDigestProduced(("event"))
Every event it consumes carries runId and tenantId from the run-event envelope (ADR-0014), so the join needs no lookups. Content never enters a projection: a timeline entry holds a receipt or artifact reference and a hash, and the Studio fetches the artifact through ArtifactService under its own permission check.
Domain model¶
RunProjection — The joined view of one run — state and steps from Run Control, attempt phases and checkpoints from the runtime, model receipts, tool receipts, context snapshots, approvals, usage states and the trace id — kept current from events. (catalog entry)
| Field | Type | Required | Description |
|---|---|---|---|
runId |
guid |
yes | |
tenantId |
string |
yes | |
projectId |
string |
yes | |
workflowId |
string |
yes | |
state |
string |
yes | Run Control vocabulary (ADR-0014). |
steps |
int |
yes | |
attempts |
int |
yes | |
modelCalls |
int |
yes | |
toolCalls |
int |
yes | |
approvalsWaiting |
int |
yes | |
uncertainEffects |
int |
yes | |
tokens |
long |
yes | |
costUsdByStatus |
json |
yes | estimated, reserved, observed, reconciled, uncertain (FUX-08) |
durationMs |
long |
no | |
traceId |
string |
yes | |
lastEventSequence |
long |
yes | |
updatedAt |
datetime |
yes |
Invariants:
- Projections are derived from events and the run journal; a discrepancy is resolved by rebuilding from Run Control, never by editing the projection.
- Usage amounts carry their status; uncertain amounts are never folded into totals.
- Content never enters a projection; entries hold hashes, receipt and artifact references.
Events: RunProjectionUpdated · Tables: RunProjections, TimelineEntries, ProjectionCheckpoints · Repository: RunProjectionRepository
OverviewProjection — Rolling aggregates per tenant, project, agent, workflow, tool and model for a window — task success, agent success, cost per task, latency per task, tokens per task, tool failure rate, model fallback rate, human intervention rate, sandbox failures, context retrieval quality, evaluation score. (catalog entry)
| Field | Type | Required | Description |
|---|---|---|---|
overviewId |
guid |
yes | |
tenantId |
string |
yes | |
kind |
enum:ProjectionKind |
yes | |
subjectId |
string |
yes | Project, agent, workflow, tool or model id. |
window |
string |
yes | 1h |
metrics |
json |
yes | |
computedAt |
datetime |
yes |
Invariants:
- Aggregates are recomputed from projections on a schedule; they are never written by hand.
Events: OperationsDigestProduced · Tables: OverviewProjections · Repository: OverviewProjectionRepository
erDiagram
RunProjection {
guid runId PK
string tenantId
string projectId
string workflowId
string state
int steps
int attempts
int modelCalls
int toolCalls
int approvalsWaiting
int uncertainEffects
long tokens
json costUsdByStatus
long durationMs
string traceId
long lastEventSequence
datetime updatedAt
}
OverviewProjection {
guid overviewId PK
string tenantId
enum_ProjectionKind kind
string subjectId
string window
json metrics
datetime computedAt
}
TimelineEntry {
long sequence
string kind
string reference
string summary
datetime occurredAt
long durationMs
decimal costUsd
}
RunProjection ||--o{ TimelineEntry : contains
Entities and value objects¶
TimelineEntry (entity, in RunProjection) — One event on the run timeline (the §51 trace tree as rows).
| Field | Type | Required | Description |
|---|---|---|---|
sequence |
long |
yes | |
kind |
string |
yes | run |
reference |
string |
yes | Receipt, snapshot, approval or decision id. |
summary |
string |
yes | |
occurredAt |
datetime |
yes | |
durationMs |
long |
no | |
costUsd |
decimal |
no |
Data model and storage¶
| Store | Role | Engine / profile | Tables |
|---|---|---|---|
| Operations projection store | read-model | azure-sql / nhibernate-sqlserver | RunProjections, TimelineEntries, ProjectionCheckpoints, OverviewProjections |
| Table | Owner | Columns | Indexes |
|---|---|---|---|
dbo.RunProjections |
RunProjection | 17 | 2 |
dbo.TimelineEntries |
TimelineEntry | 9 | 0 |
dbo.ProjectionCheckpoints |
RunProjection | 4 | 0 |
dbo.OverviewProjections |
OverviewProjection | 7 | 1 |
Full DDL: appendix.
APIs¶
| Method | Path | Operation | Scope | Side effects | Idempotency | Gateway | Summary |
|---|---|---|---|---|---|---|---|
GET |
/factory/operations/runs |
ListRunProjections | factory.runs.read |
read | natural | GW-03 | Runs in scope with state, counts, cost by status and waits; the Studio run list. |
GET |
/factory/operations/runs/{runId} |
GetRunTimeline | factory.runs.read |
read | natural | GW-03 | The §51 trace tree as a timeline: steps, attempts, model and tool receipts, context snapshots, approvals, decisions, usage. |
GET |
/factory/operations/overview |
GetOverview | factory.operations.read |
read | natural | GW-03 | Tenant and project overview metrics per window. |
GET |
/factory/operations/overview/{kind}/{subjectId} |
GetSubjectOverview | factory.operations.read |
read | natural | GW-03 | Agent performance, tool reliability or model usage for one subject. |
POST |
/factory/operations/runs/{runId}/rebuild |
RebuildRunProjection | factory.operations.admin |
shared-write | natural | GW-03 | Rebuild one run's projection from Run Control's journal and the producers' events (Operator). |
| gRPC service | Method | Streaming | Visibility | Side effects | Summary |
|---|---|---|---|---|---|
Operations |
Subscribe |
server | internal | read | Stream projection updates for runs in scope to the Studio BFF. |
Messages¶
| Event | Topic | Scope / v | Aggregate | Consumers | Summary |
|---|---|---|---|---|---|
| RunProjectionUpdated | operations.projections.v1.run-projection-updated |
integration / 1 | RunProjection | StudioRealtimeGateway, StudioBff | A run projection changed. |
| OperationsDigestProduced | operations.projections.v1.operations-digest-produced |
integration / 1 | OverviewProjection | StudioBff, SloService | Overview aggregates recomputed for a window. |
RunProjectionUpdated payload:
| Field | Type | Required | Description |
|---|---|---|---|
runId |
guid |
yes | |
tenantId |
string |
yes | |
state |
string |
yes | |
lastEventSequence |
long |
yes |
OperationsDigestProduced payload:
| Field | Type | Required | Description |
|---|---|---|---|
tenantId |
string |
yes | |
window |
string |
yes | |
computedAt |
datetime |
yes |
| Command | Handled by | Result events | Summary |
|---|---|---|---|
RebuildRunProjection |
RunProjection | RunProjectionUpdated |
| Event | Producer | Handler | Purpose |
|---|---|---|---|
| RunAccepted | RunControlService | ProjectRun |
Open the run projection. |
| RunStateChanged | RunControlService | ProjectRun |
State transitions. |
| RunCompleted | RunControlService | ProjectRun |
Terminal state and duration. |
| RunFailed | RunControlService | ProjectRun |
Terminal state and failure class. |
| AttemptDispatched | RunControlService | ProjectAttempt |
Attempts and leases. |
| AttemptOutcomeRecorded | RunControlService | ProjectAttempt |
Outcomes. |
| AttemptPhaseChanged | AgentRuntimeService | ProjectAttempt |
Phases on the timeline. |
| ModelInvoked | ModelRouterService | ProjectReceipt |
Model receipts, tokens, cost. |
| ToolInvoked | ToolAdapterService | ProjectReceipt |
Tool receipts and outcomes. |
| ContextAssembled | ContextBuilderService | ProjectContext |
Context snapshots and budgets. |
| UsageRecorded | CostUsageService | ProjectUsage |
Usage by status. |
| ReservationSettled | CostUsageService | ProjectUsage |
Settlement. |
| StepRunStateChanged | WorkflowEngineService | ProjectWorkflow |
Workflow step states. |
Workers and jobs¶
| Worker | Trigger | Output events | Retry | Idempotency key | Summary |
|---|---|---|---|---|---|
| ProjectionRebuilder | manual on RebuildRunProjection or restore |
RunProjectionUpdated | exponential | runId + lastEventSequence |
Rebuilds run projections from Run Control's journal and producers' events after a restore or on request. |
| OverviewAggregator | schedule */5 * * * * |
OperationsDigestProduced | fixed | tenantId + window + computedAt |
Recomputes overview metrics per subject and window from run projections. |
Actors and grains¶
None modelled
No grains are modelled for this item yet.
Sagas and long-running flows¶
None modelled
No sagas are modelled for this item yet.
sequenceDiagram
participant RC as RunControlService
participant MR as ModelRouterService
participant TA as ToolAdapterService
participant D as DashboardService
participant BFF as Studio BFF
RC-)D: RunAccepted / RunStateChanged / AttemptDispatched
MR-)D: ModelInvoked (receipt, tokens, cost)
TA-)D: ToolInvoked (receipt, outcome, class)
D->>D: append timeline entries, update counts and cost by status
D-)BFF: RunProjectionUpdated (stream)
Note over D: every 5 min: OverviewAggregator recomputes windows → OperationsDigestProduced
Options and configuration¶
| Section | Key | Type | Default | Reloadable | Secret | Summary |
|---|---|---|---|---|---|---|
Observability:Operations |
Windows |
string[] | [1h, 24h, 7d, 30d] |
yes | no | Overview windows. |
Observability:Operations |
TimelineMaxEntries |
int | 5000 |
yes | no | Entries kept per run timeline before archival to artifacts. |
Metrics and observability¶
| Metric | Instrument | Unit | Dimensions | Summary |
|---|---|---|---|---|
connectsoft.factory.operations.projection_lag |
gauge | s | tenant | Lag behind the newest consumed event. |
connectsoft.factory.operations.task_success_rate |
gauge | 1 | tenant, window | Share of completed runs (the §51 metric). |
connectsoft.factory.operations.human_intervention_rate |
gauge | 1 | tenant, window | Runs needing an approval or an operator action. |
connectsoft.factory.operations.cost_per_task_usd |
gauge | USD | tenant, window | Reconciled cost per completed run. |
Security¶
| Authentication | client-credentials |
| Scopes | factory.runs.read (Run projections in scope.); factory.operations.read (Overviews.); factory.operations.admin (Rebuilds (Operator).) |
| Roles | Requester, Reviewer, Operator, WorkspaceAdmin, PlatformAdmin, Observer |
| Tenant isolation | row-filter |
| Data classification | internal |
| Max side-effect class | shared-write |
| Secrets | — |
Dependencies¶
Outbound
| Target | Kind | Purpose | Failure mode | Required |
|---|---|---|---|---|
| RunControlService | grpc | Journal reads for rebuilds. | degrade | yes |
| ext-otel-backend | sync-http | Trace drill-down links. | degrade | no |
Inbound
| Target | Kind | Purpose | Failure mode | Required |
|---|---|---|---|---|
| StudioBff | sync-http | Run lists, timelines, overviews, subscriptions. | — | yes |
| SloService | event | Overview digests. | — | yes |
Failure and recovery¶
| Scenario | Detection | Recovery | Data impact | RTO (min) |
|---|---|---|---|---|
| Out-of-order events | sequence gaps per run | projection waits for the gap within a window then rebuilds from the journal | temporary stale view | 10 |
NFR targets¶
| Target | Class value (pilot-projection) | Override |
|---|---|---|
| latency_p95_ms | 500 | — |
| availability_pct | 99.5 | — |
| throughput_rps | 100 | — |
| rpo_minutes | 15 | — |
| rto_minutes | 240 | — |
| cost_class | low | — |
Deployment¶
| Granularity | module of host · host ObservabilityHost |
| Topologies | saas-default, hybrid, on-prem, hybrid-compute |
| Runtime | —; replicas —–— |
| Ports | — |
Current implementation¶
The Studio prototype shows run lists and a run detail with hard-coded data; the run-event envelope and receipts are typed in this design but no projection consumes them.
Later capabilities¶
Replay and simulation views (original design §50) that re-execute a timeline against a different release in the sandbox; per-agent cost attribution dashboards at the step level; projection snapshots exported to a tenant's own warehouse.
Decisions and traceability¶
| Family | Ids |
|---|---|
| FR | FR-10 |
| FUX | FUX-04, FUX-07, FUX-08 |
| NFR | NFR-10, NFR-07 |
| XL | XL-06, XL-12, XL-16 |