Factory Studio — aggregate roots¶
Generated from the architecture model
This page is rendered from model/**/*.yaml by tools/docs_model during mkdocs build. Edit the YAML, not this page; hand-written design lives on the linked service, platform and plane pages.
| Aggregate | Service | Root entity | Events | Tables |
|---|---|---|---|---|
| StudioSession | StudioBff | StudioSession | StudioSessionStarted | StudioSessions |
| SavedView | StudioBff | SavedView | SavedViewChanged | SavedViews |
| Notification | StudioNotificationService | Notification | NotificationCreated | Notifications |
| NotificationPreference | StudioNotificationService | NotificationPreference | — | NotificationPreferences |
| RealtimeSubscription | StudioRealtimeGateway | RealtimeSubscription | — | — |
StudioSession (StudioBff)¶
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.
| 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.
SavedView (StudioBff)¶
A user- or team-saved filter and layout for a list screen (runs, approvals, assets, alerts, fleet) with sharing scope.
| 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.
Notification (StudioNotificationService)¶
One notification for one user: kind, subject reference, scope, importance, read and dismissed state, and the deliveries made per channel with receipts.
| Field | Type | Required | Description |
|---|---|---|---|
notificationId |
guid |
yes | |
tenantId |
string |
yes | |
userId |
string |
yes | |
kind |
enum:NotificationKind |
yes | |
subjectRef |
string |
yes | |
projectId |
string |
no | |
importance |
string |
yes | info |
summary |
string |
yes | |
readAt |
datetime |
no | |
dismissedAt |
datetime |
no | |
deliveries |
json |
yes | |
createdAt |
datetime |
yes |
Invariants
- A notification is created only for users whose scope and role allow seeing the subject; the fan-out resolves recipients through the owning platform's permission check, never from the event alone.
- Content is a summary with a reference; the Studio fetches the subject under the user's permissions when opened.
NotificationPreference (StudioNotificationService)¶
Per-user channel preferences, quiet hours and digest settings per notification kind.
| Field | Type | Required | Description |
|---|---|---|---|
userId |
string |
yes | |
tenantId |
string |
yes | |
channelsByKind |
json |
yes | |
quietHours |
json |
no | |
digest |
string |
yes | none |
Invariants
- Action-required and critical notifications ignore quiet hours for the in-app channel.
RealtimeSubscription (StudioRealtimeGateway)¶
One session's subscription to one stream with its scope filter, the upstream gRPC stream or inbox it is served from, backpressure state and the last sequence delivered.
| Field | Type | Required | Description |
|---|---|---|---|
subscriptionId |
guid |
yes | |
tenantId |
string |
yes | |
sessionId |
guid |
yes | |
connectionId |
string |
yes | |
kind |
enum:StreamKind |
yes | |
filter |
json |
yes | run id, project, environment, product |
lastSequence |
long |
yes | |
backpressure |
bool |
yes | |
startedAt |
datetime |
yes |
Invariants
- A subscription is created only after the BFF confirmed the session may read the subject; the filter cannot widen the session's scope.
- On reconnect the client resumes from the last sequence; gaps beyond the buffer trigger a full refresh of the screen, never a silent skip.