Skip to content

StudioBff

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-29 Experience Composition
Platform / plane Factory Studio / Experience
Deployment granularity standalone host
Status target · ConnectSoft.Factory.Studio
Built from connectsoft-apigateway · libraries: connectsoft-extensions-saas-abstractions, connectsoft-extensions-saas-asp-net-core, connectsoft-extensions-messaging-model, connectsoft-extensions-persistence-model-nhibernate, connectsoft-extensions-service-model-signal-r, connectsoft-extensions-observability, connectsoft-extensions-query-model
Decisions ADR-0014, ADR-0015, ADR-0016
Traceability FR-01 FR-05 FR-10 FUX-01 FUX-02 FUX-03 FUX-04 FUX-06 FUX-07 FUX-08 FUX-09 FUX-11 FUX-12 NFR-01 NFR-02 NFR-03 NFR-10 XL-01 XL-05 XL-06 XL-12

Purpose and responsibilities

StudioBff is gateway role GW-02: the one service the Studio's Blazor shell, microfrontends, CLI and VS Code extension talk to. For every screen in the UX model it builds a composition — runs from Run Control and the operations projections, approvals, assets and releases, evaluation verdicts, alerts, fleet, delivery, provisioning, knowledge — each source read under the session's execution scope and each marked with its projection freshness, so a stale or degraded source is visible rather than hidden. For every action it forwards a command to the owning platform with an idempotency key, the session's scope and, for gated classes, the approval binding; the class and gates are the owning service's, never the BFF's. It keeps the session projection (scope switchers that grant nothing, permissions snapshot, locale, theme, reduced motion, work area), saved views and preferences, and hosts StudioNotificationService.

It absorbs the June-2026 AgentFlowVisualizationService, DashboardAggregationService, KnowledgeExplorerBff and KnowledgeStudioBff: they are compositions over other platforms' projections, not services with state.

Context and boundaries

flowchart LR
    S["StudioBff"]
    StudioRealtimeGateway["StudioRealtimeGateway"] -->|grpc| S
    S -->|sync-http| ext_identity_platform["ext-identity-platform"]
    S -->|grpc| ControlPlaneApi["ControlPlaneApi"]
    S -->|grpc| ObservabilityHost["ObservabilityHost"]
    S -->|grpc| KnowledgeHost["KnowledgeHost"]
    S -->|grpc| GovernanceHost["GovernanceHost"]
    S -->|grpc| ModelGatewayHost["ModelGatewayHost"]
    S -->|grpc| ToolExecutorHost["ToolExecutorHost"]
    S -->|grpc| IntegrationHost["IntegrationHost"]
    S -->|grpc| DeliveryHost["DeliveryHost"]
    S -->|grpc| RuntimeCloudHost["RuntimeCloudHost"]
    S -->|grpc| FleetOperationsHost["FleetOperationsHost"]
    S -->|grpc| DataEventFoundations["DataEventFoundations"]
    S -->|sync-http| ext_config_platform["ext-config-platform"]
    S -. "StudioSessionStarted" .-> E_StudioSessionStarted(("event"))
    S -. "SavedViewChanged" .-> E_SavedViewChanged(("event"))
Hold "Alt" / "Option" to enable pan & zoom

The BFF is built on the ConnectSoft API gateway template (GW-01 fronts it) with the Blazor shell, microfrontend library and UIKit as its clients. The seven work areas and the screen inventory come from the UX model (model/ux/, design plan U1–U2); this service is the contract they compose against.

Domain model

StudioSession — The per-user session projection: the resolved execution scope (organization, tenant, project, environment switchers that grant nothing by themselves), roles and effective permissions snapshot, locale, theme, reduced-motion preference, current work area and the realtime subscriptions the session holds. (catalog entry)

Field Type Required Description
sessionId guid yes
tenantId string yes
userId string yes
scope json yes execution-scope-v1: tenant, project, environment
permissionsSnapshot json yes
locale enum:Locale yes
theme string yes light
reducedMotion bool yes
workArea enum:WorkArea yes
subscriptions list:string yes
startedAt datetime yes
lastSeenAt datetime yes

Invariants:

  • A switcher changes the scope the session reads under; it never grants a permission the identity platform and the Control plane did not grant (ADR-0015).
  • Every composed response is filtered by the owning platform under the session's scope; the BFF never widens a result set.

Events: StudioSessionStarted · Tables: StudioSessions · Repository: StudioSessionRepository

SavedView — A user- or team-saved filter and layout for a list screen (runs, approvals, assets, alerts, fleet) with sharing scope. (catalog entry)

Field Type Required Description
viewId guid yes
tenantId string yes
ownerUserId string yes
screenId string yes
name string yes
definition json yes
sharedWith string yes private
updatedAt datetime yes

Invariants:

  • A shared view carries no data, only a filter definition; results are still scoped per viewer.

Events: SavedViewChanged · Tables: SavedViews · Repository: SavedViewRepository

erDiagram
    StudioSession {
        guid sessionId PK
        string tenantId
        string userId
        json scope
        json permissionsSnapshot
        enum_Locale locale
        string theme
        bool reducedMotion
        enum_WorkArea workArea
        list_string subscriptions
        datetime startedAt
        datetime lastSeenAt
    }
    SavedView {
        guid viewId PK
        string tenantId
        string ownerUserId
        string screenId
        string name
        json definition
        string sharedWith
        datetime updatedAt
    }
Hold "Alt" / "Option" to enable pan & zoom

Entities and value objects

None modelled

No entities or value objects are modelled for this item yet.

Data model and storage

Store Role Engine / profile Tables
Studio store primary azure-sql / nhibernate-sqlserver StudioSessions, SavedViews
Cache and coordination cache redis / azure-cache —
Table Owner Columns Indexes
dbo.StudioSessions StudioSession 12 1
dbo.SavedViews SavedView 8 1

Full DDL: appendix.

APIs

Method Path Operation Scope Side effects Idempotency Gateway Summary
GET /studio/session GetStudioSession factory.studio.use read natural GW-02 The session projection: scope, permissions snapshot, locale, theme, work area, feature flags from the Config Platform.
PUT /studio/session/scope SetStudioScope factory.studio.use shared-write natural GW-02 Switch tenant, project or environment (validated against the identity platform and Control; grants nothing).
PUT /studio/session/preferences SetStudioPreferences factory.studio.use shared-write natural GW-02 Locale (en, he, ru), theme, reduced motion, default work area.
GET /studio/screens/{screenId} GetScreenModel factory.studio.use read natural GW-02 A screen-shaped composition for one of the UX model's screens (runs, approvals, assets, evaluation, operations, fleet, …) built from the owning platforms' read models under the session's scope, with projection freshness per source.
POST /studio/commands/{commandId} ForwardCommand factory.studio.use production key-header GW-02 Forward a Studio command (submit run, decide approval, acknowledge alert, request promotion, …) to the owning platform with an idempotency key, the session's scope and, for gated classes, the approval binding; the class and the owning service's gates apply, never the BFF's.
GET /studio/views ListSavedViews factory.studio.use read natural GW-02 Saved views visible to the user for a screen.
PUT /studio/views/{viewId} SaveView factory.studio.use shared-write natural GW-02 Create or update a saved view.
GET /studio/search StudioSearch factory.studio.use read natural GW-02 Command-palette search across runs, assets, projects, environments, alerts and screens under the session's scope.
GET /studio/health StudioHealth factory.health.read read natural GW-01 Liveness and readiness with per-source dependency health.

None modelled

No gRPC methods are modelled for this item yet.

Messages

Event Topic Scope / v Aggregate Consumers Summary
StudioSessionStarted studio.sessions.v1.studio-session-started integration / 1 StudioSession AuditService, DashboardService A Studio session started (audit of scope and locale).
SavedViewChanged studio.views.v1.saved-view-changed integration / 1 SavedView StudioRealtimeGateway A saved view was created, changed or deleted.

StudioSessionStarted payload:

Field Type Required Description
sessionId guid yes
tenantId string yes
userId string yes
locale enum:Locale yes

SavedViewChanged payload:

Field Type Required Description
viewId guid yes
tenantId string yes
screenId string yes
sharedWith string yes
Command Handled by Result events Summary
SetStudioScope StudioSession —
SaveView SavedView SavedViewChanged

None modelled

No consumed events are modelled for this item yet.

Workers and jobs

Worker Trigger Output events Retry Idempotency key Summary
SessionSweeper schedule */15 * * * * — none sessionId Expires idle sessions and releases their realtime subscriptions.

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 UI as Studio shell / MFE
    participant B as StudioBff
    participant RC as RunControlService
    participant D as DashboardService
    participant Q as QualityScoreService
    UI->>B: GET /studio/screens/run-detail?runId
    par compose under the session's scope
        B->>RC: run, steps, approvals (scope)
        B->>D: timeline projection (scope) + freshness
        B->>Q: evaluation verdicts for the agent release
    end
    B-->>UI: composition with per-source freshness and permissions per action
    UI->>B: POST /studio/commands/decide-approval (idempotency key)
    B->>RC: DecideApproval (user token, scope, approval id, version)
    RC-->>B: 200 / 403 / 409 / 412
    B-->>UI: outcome, never retried by the BFF
Hold "Alt" / "Option" to enable pan & zoom

Options and configuration

Section Key Type Default Reloadable Secret Summary
Studio:Bff ScreenCacheSeconds int 5 yes no Short cache per screen composition keyed by scope.
Studio:Bff SupportedLocales string[] [en, he, ru] no no Locales offered; he is right-to-left.
Studio:Bff SessionIdleMinutes int 120 yes no Idle timeout.

Metrics and observability

Metric Instrument Unit Dimensions Summary
connectsoft.factory.studio.screen_latency histogram ms screenId Screen composition latency (NFR interactive 2 s p95).
connectsoft.factory.studio.commands_forwarded counter {command} commandId, outcome Commands forwarded by outcome.
connectsoft.factory.studio.sessions_active updown {session} tenant, locale Active sessions.
connectsoft.factory.studio.source_degraded updown {source} source Sources currently degraded in compositions.

Security

Authentication oauth2-jwt
Scopes factory.studio.use (Use the Studio under the user's own grants (every forwarded call carries the user's token and scope).); factory.health.read (Health probes.)
Roles Requester, Reviewer, AssetMaintainer, Operator, WorkspaceAdmin, PlatformAdmin, Observer
Tenant isolation per-request-claim
Data classification internal
Max side-effect class production
Secrets studio-sql (key-vault, rotate 90 d); studio-signing (key-vault, rotate 90 d)

Dependencies

Outbound

Target Kind Purpose Failure mode Required
ext-identity-platform sync-http User authentication (OpenIddict) and token exchange for downstream calls. fail-fast yes
ControlPlaneApi grpc Runs, approvals, assets, projects, environments, usage, commercial; command forwarding. degrade yes
ObservabilityHost grpc Operations, SLO, alert, evaluation and feedback views. degrade yes
KnowledgeHost grpc Knowledge, artifacts and memory views. degrade yes
GovernanceHost grpc Policy, audit and secret-reference views. degrade yes
ModelGatewayHost grpc Model profile and deployment views. degrade yes
ToolExecutorHost grpc Tool and MCP registry views. degrade yes
IntegrationHost grpc Connection and connector views. degrade yes
DeliveryHost grpc Delivery views. degrade yes
RuntimeCloudHost grpc Provisioning, inventory and capacity views. degrade yes
FleetOperationsHost grpc Fleet views. degrade yes
DataEventFoundations grpc Registry, store, retention views. degrade yes
ext-config-platform sync-http Feature flags and Studio configuration. degrade no

Inbound

Target Kind Purpose Failure mode Required
StudioRealtimeGateway grpc Session and subscription resolution. — yes

Failure and recovery

Scenario Detection Recovery Data impact RTO (min)
One source platform down dependency health the composition renders the other sources and marks the missing one degraded with its last freshness; commands to that platform are refused with 503, never queued by the BFF none 0
Identity platform down token validation failures existing sessions continue until token expiry; new sign-ins fail; status page shows it none 30

NFR targets

Target Class value (pilot-interactive) Override
latency_p95_ms 2000 —
availability_pct 99.5 —
throughput_rps 50 —
rpo_minutes 15 —
rto_minutes 240 —
cost_class low —

Deployment

Granularity standalone host
Topologies saas-default, hybrid, on-prem
Runtime aks; replicas 2–8
Ports https 8200, grpc 8202, silo 12200, gateway 31200

Current implementation

ConnectSoft.ApiGatewayTemplate, the Blazor shell and microfrontend library, ConnectSoft.Blazor.UIKit and OpenIddict exist as template foundations; the 41 design prototypes show screens with hard-coded data. No BFF, composition, session projection or command forwarding exists.

Later capabilities

Per-screen GraphQL-style field selection to cut payloads for the VS Code extension; offline-tolerant command queue in the CLI with server-side idempotency; tenant-branded Studio themes.

Decisions and traceability

Family Ids
FR FR-01, FR-05, FR-10
FUX FUX-01, FUX-02, FUX-03, FUX-04, FUX-06, FUX-07, FUX-08, FUX-09, FUX-11, FUX-12
NFR NFR-01, NFR-02, NFR-03, NFR-10
XL XL-01, XL-05, XL-06, XL-12