digraph automats { graph [rankdir=TB, splines=spline, overlap=false, bgcolor="#1e2430", nodesep=0.95, ranksep=1.0, pad=0.5, fontname="Helvetica", compound=true, mclimit=1.0]; node [shape=plaintext, fontname="Helvetica"]; edge [fontname="Helvetica", fontsize=9, penwidth=1.4, arrowsize=0.7]; subgraph cluster_session_realtime { label="Session & Real-Time Hub"; labeljust="l"; fontsize=15; style="rounded,filled"; fillcolor="#202a3a"; color="#3f4c5f"; fontcolor="#e2e8f0"; margin=14; authAutomat [label=<
authAutomat
Always-On Session & Multi-Tenant Gateway
STATEhasAuth: booleanAuthenticated session bit
STATEhasCompany: booleanhasAuth && selectedCompanyId
STATEuser: AuthUserCurrent user & company
STATEstatus'anon' | 'authed' | 'loading'
ACTIONbootstrapSession()Restore or fetch session
ACTIONswitchCompany(id)Multi-tenant switch
ACTIONlogout()Clear session cookie
SELECTselectHasAuth() / selectHasCompany()Auth & tenant gates
APIGET /api/auth/sessionCookie session check
>]; sseAutomat [label=<
sseAutomat
Single Persistent SSE Connection
STATEstatus'connected' | 'error'
STATEclientId (cid)Tab-scoped UUID in session
ACTIONreconnect()Cycle on company switch
ACTIONon(event, handler)Register signal listener
ACTIONwatchArticle(sku)Attach article-<sku>
SELECTinvalidateArticle(sku)Silent cache refresh
SSEcategory / articlesCatalog mutation events
SSEorder / shipmentFulfillment events
APIGET /api/eventsPersistent stream
>]; } subgraph cluster_company_basedata { label="Company & Consolidated Base Data"; labeljust="l"; fontsize=15; style="rounded,filled"; fillcolor="#202a3a"; color="#3f4c5f"; fontcolor="#e2e8f0"; margin=14; companyAutomat [label=<
companyAutomat
Consolidated Company & Base Data Hub
STATEcurrent: CompanyTax rates, legal & root cat
STATEnumbers: NumberSeq[]Document number sequences
STATEterminals: Posterminal[]POS hardware & categories
STATEsuppliers: Supplier[]Vendors & supplier articles
STATEunits: Unit[]Allowed SI & sales units
STATEviewerPosition / chatDrawerWidthPersisted user UI settings
STATEwarehouses: Warehouse[]Storage locations & stock
STATEproperties: PropertyName[]Custom text properties
STATEcustomergroups: Group[]Pricing discount tiers
STATEcarriers: Carrier[]Shipping methods & carriers
STATEbrands: Brand[]Catalog brands & logos
STATEattributes: AttributeName[]Attributes & discrete values
STATEaccounts: Account[]Bank & payment ledgers
ACTIONloadAll() / reset()Fetch or reset all base data
SELECTselectCompanyRootCategoryId()Root category pointer
API/api/company, /api/brand, …13 consolidated endpoints
>]; } subgraph cluster_catalog_products { label="Catalog & Products"; labeljust="l"; fontsize=15; style="rounded,filled"; fillcolor="#202a3a"; color="#3f4c5f"; fontcolor="#e2e8f0"; margin=14; categoryAutomat [label=<
categoryAutomat
Hierarchical Category Tree
STATEcategories: MapID -> Category Node Map
STATErootCategoryIdCompany root node ID
STATEarticleCountTotal parent items
ACTIONloadTree()Fetch tree & warm views
ACTIONcreateCategory()Insert child node
ACTIONmoveCategory()Parent reparenting
ACTIONdeleteCategory()Prune subtree
SELECTgetCategoryBreadcrumbs()Hierarchical path trace
APIGET /api/categoryRecursive tree load
>]; categoryViewAutomat [label=<
categoryViewAutomat
KeyedAutomat (Slug Path)
STATEviews: Map<slug, Data>Articles & direct children
ACTIONloadAllCategoryViews()Prewarm all tree slugs
ACTIONreloadLoadedCategoryViews()Refresh cached views
ACTIONinvalidateAllCategoryViews()Clear on SSE signal
SELECTcollectLoadedCategoryViewData()Extract union data
SELECTgetOrCreateCategoryAutomat()Per-slug reactive store
APIGET /api/category/:id/articlesCategory article batch
>]; artikelAutomat [label=<
artikelAutomat
In-Memory Article Record Cache
STATEarticles: Map<sku, Object>Deduplicated SKU cache
ACTIONloadArticle(sku)Fetch or cached promise
ACTIONreloadArticle(sku)Silent background sync
ACTIONsetArticleName(sku, name)Optimistic rename
ACTIONclearArticle(sku)Evict SKU from cache
SELECTgetArticle(sku)Sync constructor read
SELECTcreateArticleSelector(sku)Fine-grained selector
APIGET /api/article/:skuFull article document
>]; articleDetailAutomat [label=<
articleDetailAutomat
KeyedAutomat (SKU)
STATEarticleHistory: Map<sku>Change history log
STATEarticleSupplier: Map<sku>Assigned supplier list
ACTIONarticleHistoryAutomat.load()Fetch SKU audit trail
ACTIONarticleSupplierAutomat.load()Fetch supplier catalog
APIGET /api/article/:sku/historyAudit change entries
APIGET /api/article/:sku/supplierVendor links & prices
>]; } subgraph cluster_search_indexing { label="Search & Indexing"; labeljust="l"; fontsize=15; style="rounded,filled"; fillcolor="#202a3a"; color="#3f4c5f"; fontcolor="#e2e8f0"; margin=14; articleIndexAutomat [label=<
articleIndexAutomat
Derived Client Search Index
STATEitems: ArticleIndexRecord[]De-duplicated article union
STATEstatus: 'ready'Index lifecycle flag
ACTIONbuildArticleIndex()Derive from category views
ACTIONsetArticleIndexName()Patch on rename
ACTIONreload()Re-derive from views
SELECTselectArticleIndexItems()Fast record projection
SELECTensureLoaded()Await warm views
>]; articleSearchAutomat [label=<
articleSearchAutomat
In-Memory FlexSearch Engine
STATEtarget: stringActive search query
STATEfilter: stringActive category filter
STATEresult: ArticleSearchResultFacets, recordset, count
ACTIONsearch(target, filter)Synchronous indexed query
SELECTselectSearchResult()Reactive search outcome
>]; } subgraph cluster_purchasing_logistics { label="Deliveries & Inbound"; labeljust="l"; fontsize=15; style="rounded,filled"; fillcolor="#202a3a"; color="#3f4c5f"; fontcolor="#e2e8f0"; margin=14; deliveryAutomat [label=<
deliveryAutomat
Chunk-Paginated Deliveries
STATEitems: Delivery[]Company delivery receipts
STATEstatus: 'ready'List lifecycle state
ACTIONload() / reload()Deduplicated fetch & sync
ACTIONreset()Clear on session switch
APIGET /api/deliveryInbound delivery log
>]; deliveryEditorAutomat [label=<
deliveryEditorAutomat
Inbound Receipt & OCR Machine
STATElines: DeliveryLine[]Uncommitted draft lines
STATEdeliveryEntitySelected supplier ID
STATEattachments: File[]Invoice PDFs & OCR results
STATEdraftCount: numberUncommitted lines for badge
ACTIONaddLine() / updateLine()Interactive item editing
ACTIONcommitDelivery()Persist goods receipt
SELECTbuildSupplierArticlesMap()Auto-match SKU/EAN
APIPOST /api/deliveryCreate goods receipt
>]; } subgraph cluster_sales_crm { label="Sales & CRM"; labeljust="l"; fontsize=15; style="rounded,filled"; fillcolor="#202a3a"; color="#3f4c5f"; fontcolor="#e2e8f0"; margin=14; quoteAutomat [label=<
quoteAutomat
Chunk-Paginated Quotes
STATEitems: Quote[]Sales quotes / Angebote
ACTIONload() / reload()Deduplicated fetch
ACTIONreset()Reset on logout
APIGET /api/quoteCompany quote list
>]; orderAutomat [label=<
orderAutomat
Chunk-Paginated Order Engine
STATEitems: Order[]Sales orders & lines
STATEtotal: numberUnfiltered order count
STATEonlyUnpaid / onlyUndeliveredFulfillment filters
ACTIONloadChunk(index)Chunk size 50 prefetch
ACTIONreload()Silent orders re-fetch
SELECTselectOrders() / selectTotal()Filter-applied slice
APIGET /api/orderPaged order stream
SSEorder / shipmentFulfillment mutations
>]; entityAutomat [label=<
entityAutomat
Customer & Partner Directory
STATEitems: Entity[]Customers & partners
ACTIONload() / reload()Customer directory load
ACTIONreset()Reset on session switch
APIGET /api/entityDirectory records
>]; } subgraph cluster_ai_workspace { label="AI Assistant & Workspace"; labeljust="l"; fontsize=15; style="rounded,filled"; fillcolor="#202a3a"; color="#3f4c5f"; fontcolor="#e2e8f0"; margin=14; chatAutomat [label=<
chatAutomat
AI Assistant Drawer & SSE
STATEisOpen: booleanDocked chat drawer toggle
STATEconversations: []Conversation sessions
STATEmessages: ModelMessage[]Live message transcript
STATEsseStatus: 'connected'Token streaming stream
ACTIONsendMessage(text)Prompt model with tools
ACTIONanswerAskUser()Interactive tool modal
SELECTuserEnv / routeToolsClient navigation tool
APIPOST /api/modelconversationAI conversation session
SSEmodelconversation/eventsLive token stream
>]; vfsAutomat [label=<
vfsAutomat
Virtual Filesystem Explorer
STATEfiles: VfsFile[]Company VFS workspace
STATEselectedFileNameCurrent active file
STATEfileContent / isDirtyEditor buffer & diff
ACTIONselectFile() / saveFile()Applet editor buffer
ACTIONuploadFiles() / deleteFile()File manipulations
APIGET /api/vfsVFS directory index
SSEvfsVFS mutation signal
>]; } subgraph cluster_audit_grids { label="Audit & Virtual Grids"; labeljust="l"; fontsize=15; style="rounded,filled"; fillcolor="#202a3a"; color="#3f4c5f"; fontcolor="#e2e8f0"; margin=14; articleHistoryGridAutomat [label=<
articleHistoryGridAutomat
createGridAutomat (Article)
STATErows: [] / totalRowsBlock size 50 virtual rows
ACTIONfetchRows(viewport)Infinite scroll query
ACTIONreload()Reload on company switch
APIGET /api/article/historyInfinite audit window
>]; globalHistoryGridAutomat [label=<
globalHistoryGridAutomat
createGridAutomat (Global)
STATErows: [] / totalRowsBlock size 50 virtual rows
ACTIONfetchRows(viewport)Infinite scroll query
ACTIONreload()Reload on company switch
APIGET /api/globalhistoryCompany global audit
>]; ledgerHistoryGridAutomat [label=<
ledgerHistoryGridAutomat
createGridAutomat (Ledger)
STATErows: [] / totalRowsBlock size 50 virtual rows
ACTIONfetchRows(viewport)Infinite scroll query
ACTIONreload()Reload on company switch
APIGET /api/ledger/historyAppend-only ledger audit
>]; } subgraph cluster_system_ui { label="UI, Navigation & System"; labeljust="l"; fontsize=15; style="rounded,filled"; fillcolor="#202a3a"; color="#3f4c5f"; fontcolor="#e2e8f0"; margin=14; navigationAutomat [label=<
navigationAutomat
Cross-Section Navigation Memory
STATElastDeliveryPathActive receipt subpath
STATElastArticleSkuActive SKU selection
STATElastCategorySlug / PathActive category tree node
STATElastSearchTerm / PathPreserved search query
ACTIONsetLastDeliveryPath()Restore on sidebar click
ACTIONsetLastArticleSku()Restore SKU on section click
ACTIONclearNavigation()Reset on company switch
>]; helpAutomat [label=<
helpAutomat
IndexedDB Contextual Help
STATEenabled: booleanInteractive help badges
STATEactiveHelpId: string|nullActive popper ID
ACTIONtoggle() / setEnabled()Toggle badge mode
ACTIONopenPopper() / closePopper()Single active popper
HOOKpersist: trueSurvives page reloads
>]; pwaAutomat [label=<
pwaAutomat
Service Worker & Offline Lifecycle
STATEneedRefresh: booleanNew SW release pending
STATEofflineReady: booleanOffline assets cached
STATEdialogOpen / updatingPrompt modal state
ACTIONapplyUpdate()Skip waiting & reload
ACTIONopenDialog() / closeDialog()Modal controls
>]; Legend [label=<
Automat Graph Legend
STATEReactive store state property
ACTIONState mutation action
SELECTReactive PureComponent selector
APIBackend REST/Fetch endpoint
SSEInbound Server-Sent Event trigger
HOOKAuth / persistence lifecycle hook
in#Inbound arrival port on Automat header
▪—▶Reactive dataflow / upstream trigger
>]; } authAutomat:p_auth_hasAuth:e -> sseAutomat:in0:n [color="#5aa7ff", fontcolor="#5aa7ff", tooltip="authAutomat → sseAutomat (hasAuth -> connect SSE)", label=" hasAuth -> connect SSE ", constraint=false, weight=1]; authAutomat:p_auth_hasCompany:e -> companyAutomat:in0:n [color="#6bdf9a", fontcolor="#6bdf9a", tooltip="authAutomat → companyAutomat (hasCompany -> loadAll())", label=" hasCompany -> loadAll() ", constraint=false, weight=1]; authAutomat:p_auth_hasCompany:w -> categoryAutomat:in2:n [color="#f5c15c", fontcolor="#f5c15c", tooltip="authAutomat → categoryAutomat (sync tree on hasCompany)", label=" sync tree on hasCompany ", constraint=false, weight=1]; authAutomat:p_auth_status:e -> deliveryAutomat:in0:n [color="#ff7fc2", fontcolor="#ff7fc2", tooltip="authAutomat → deliveryAutomat (sync deliveries on authed)", label=" sync deliveries on authed ", constraint=false, weight=1]; authAutomat:p_auth_status:e -> quoteAutomat:in0:n [color="#c79bff", fontcolor="#c79bff", tooltip="authAutomat → quoteAutomat (sync quotes on authed)", label=" sync quotes on authed ", constraint=false, weight=1]; authAutomat:p_auth_status:e -> orderAutomat:in0:n [color="#5cd6d6", fontcolor="#5cd6d6", tooltip="authAutomat → orderAutomat (sync orders on authed)", label=" sync orders on authed ", constraint=false, weight=1]; authAutomat:p_auth_status:e -> entityAutomat:in0:n [color="#ff9f5a", fontcolor="#ff9f5a", tooltip="authAutomat → entityAutomat (sync entities on authed)", label=" sync entities on authed ", constraint=false, weight=1]; authAutomat:p_auth_status:e -> chatAutomat:in0:n [color="#8f95ff", fontcolor="#8f95ff", tooltip="authAutomat → chatAutomat (auth chat & reload)", label=" auth chat & reload ", weight=3]; authAutomat:p_auth_status:e -> vfsAutomat:in0:n [color="#ff6b6b", fontcolor="#ff6b6b", tooltip="authAutomat → vfsAutomat (load company vfs)", label=" load company vfs ", constraint=false, weight=1]; authAutomat:p_auth_status:e -> articleHistoryGridAutomat:in0:n [color="#58d18a", fontcolor="#58d18a", tooltip="authAutomat → articleHistoryGridAutomat (reload history on authed)", label=" reload history on authed ", constraint=false, weight=1]; authAutomat:p_auth_status:e -> globalHistoryGridAutomat:in0:n [color="#4fc4e8", fontcolor="#4fc4e8", tooltip="authAutomat → globalHistoryGridAutomat (reload audit on authed)", label=" reload audit on authed ", constraint=false, weight=1]; authAutomat:p_auth_status:e -> ledgerHistoryGridAutomat:in0:n [color="#a98cff", fontcolor="#a98cff", tooltip="authAutomat → ledgerHistoryGridAutomat (reload ledger on authed)", label=" reload ledger on authed ", constraint=false, weight=1]; sseAutomat:p_sse_events:w -> categoryAutomat:in3:n [color="#ff8f66", fontcolor="#ff8f66", tooltip="sseAutomat → categoryAutomat ('category' sse trigger)", label=" 'category' sse trigger ", constraint=false, weight=1]; sseAutomat:p_sse_events:w -> categoryViewAutomat:in1:n [color="#4ecb8f", fontcolor="#4ecb8f", tooltip="sseAutomat → categoryViewAutomat (invalidate views on sse)", label=" invalidate views on sse ", constraint=false, weight=1]; sseAutomat:p_sse_events:w -> articleIndexAutomat:in2:n [color="#ff7aa8", fontcolor="#ff7aa8", tooltip="sseAutomat → articleIndexAutomat ('articles' sse trigger)", label=" 'articles' sse trigger ", constraint=false, weight=1]; sseAutomat:p_sse_events:w -> artikelAutomat:in2:n [color="#e0b25a", fontcolor="#e0b25a", tooltip="sseAutomat → artikelAutomat ('article-<sku>' sse reload)", label=" 'article-<sku>' sse reload ", weight=3]; sseAutomat:p_sse_events:w -> articleDetailAutomat:in0:n [color="#56c8c8", fontcolor="#56c8c8", tooltip="sseAutomat → articleDetailAutomat (invalidateArticle(sku))", label=" invalidateArticle(sku) ", constraint=false, weight=1]; sseAutomat:p_sse_events:e -> companyAutomat:in1:n [color="#ff5f9e", fontcolor="#ff5f9e", tooltip="sseAutomat → companyAutomat (warehouse/supplier/brand/attr/prop/carrier sse)", label=" warehouse/supplier/brand/attr/prop/carrier sse ", constraint=false, weight=1]; sseAutomat:p_sse_events:e -> orderAutomat:in1:n [color="#ffb25a", fontcolor="#ffb25a", tooltip="sseAutomat → orderAutomat ('order'/'shipment' sse)", label=" 'order'/'shipment' sse ", constraint=false, weight=1]; sseAutomat:p_sse_events:e -> vfsAutomat:in2:n [color="#66b3ff", fontcolor="#66b3ff", tooltip="sseAutomat → vfsAutomat ('vfs' sse mutation)", label=" 'vfs' sse mutation ", constraint=false, weight=1]; companyAutomat:p_comp_root:w -> categoryAutomat:in4:n [color="#5aa7ff", fontcolor="#5aa7ff", tooltip="companyAutomat → categoryAutomat (rootCategoryId & terminals)", label=" rootCategoryId & terminals ", constraint=false, weight=1]; categoryAutomat:p_cat_loadTree:e -> categoryViewAutomat:in0:n [color="#6bdf9a", fontcolor="#6bdf9a", tooltip="categoryAutomat → categoryViewAutomat (attachTree & warm slugs)", label=" attachTree & warm slugs ", weight=3]; categoryViewAutomat:p_catview_collect:e -> articleIndexAutomat:in1:n [color="#f5c15c", fontcolor="#f5c15c", tooltip="categoryViewAutomat → articleIndexAutomat (derived union index)", label=" derived union index ", weight=3]; articleIndexAutomat:p_idx_items:e -> articleSearchAutomat:in1:n [color="#ff7fc2", fontcolor="#ff7fc2", tooltip="articleIndexAutomat → articleSearchAutomat (query index items)", label=" query index items ", weight=3]; categoryAutomat:p_cat_categories:e -> articleSearchAutomat:in0:n [color="#c79bff", fontcolor="#c79bff", tooltip="categoryAutomat → articleSearchAutomat (categoryFacets)", label=" categoryFacets ", constraint=false, weight=1]; artikelAutomat:p_art_setName:e -> articleIndexAutomat:in0:n [color="#5cd6d6", fontcolor="#5cd6d6", tooltip="artikelAutomat → articleIndexAutomat (setArticleIndexName (optimistic))", label=" setArticleIndexName (optimistic) ", constraint=false, weight=1]; artikelAutomat:p_art_set:e -> categoryAutomat:in0:n [color="#ff9f5a", fontcolor="#ff9f5a", tooltip="artikelAutomat → categoryAutomat (articleCount updates)", label=" articleCount updates ", weight=3]; articleDetailAutomat:p_artdet_hist:w -> artikelAutomat:in1:n [color="#8f95ff", fontcolor="#8f95ff", tooltip="articleDetailAutomat → artikelAutomat (watch SKU details)", label=" watch SKU details ", weight=3]; deliveryEditorAutomat:p_deled_supplier:w -> companyAutomat:in2:n [color="#ff6b6b", fontcolor="#ff6b6b", tooltip="deliveryEditorAutomat → companyAutomat (match vendor catalog)", label=" match vendor catalog ", constraint=false, weight=1]; deliveryEditorAutomat:p_deled_lines:w -> artikelAutomat:in4:n [color="#58d18a", fontcolor="#58d18a", tooltip="deliveryEditorAutomat → artikelAutomat (lookup SKU & pack units)", label=" lookup SKU & pack units ", constraint=false, weight=1]; deliveryEditorAutomat:p_deled_commit:e -> deliveryAutomat:in1:n [color="#4fc4e8", fontcolor="#4fc4e8", tooltip="deliveryEditorAutomat → deliveryAutomat (commit delivery receipt)", label=" commit delivery receipt ", weight=3]; quoteAutomat:p_quote_items:e -> orderAutomat:in2:n [color="#a98cff", fontcolor="#a98cff", tooltip="quoteAutomat → orderAutomat (convert quote to order)", label=" convert quote to order ", weight=3]; orderAutomat:p_order_items:e -> entityAutomat:in1:n [color="#ff8f66", fontcolor="#ff8f66", tooltip="orderAutomat → entityAutomat (customer lookup)", label=" customer lookup ", weight=3]; chatAutomat:p_chat_msg:e -> vfsAutomat:in1:n [color="#4ecb8f", fontcolor="#4ecb8f", tooltip="chatAutomat → vfsAutomat (inspect / edit applets)", label=" inspect / edit applets ", constraint=false, weight=1]; chatAutomat:p_chat_tools:e -> navigationAutomat:in0:n [color="#ff7aa8", fontcolor="#ff7aa8", tooltip="chatAutomat → navigationAutomat (set_user_route tool)", label=" set_user_route tool ", constraint=false, weight=1]; chatAutomat:p_chat_sse:e -> sseAutomat:in1:n [color="#e0b25a", fontcolor="#e0b25a", tooltip="chatAutomat → sseAutomat (getSseClientId())", label=" getSseClientId() ", weight=3]; navigationAutomat:p_nav_sku:w -> artikelAutomat:in3:n [color="#56c8c8", fontcolor="#56c8c8", tooltip="navigationAutomat → artikelAutomat (restore last SKU)", label=" restore last SKU ", constraint=false, weight=1]; navigationAutomat:p_nav_catslug:w -> categoryAutomat:in5:n [color="#ff5f9e", fontcolor="#ff5f9e", tooltip="navigationAutomat → categoryAutomat (restore last category)", label=" restore last category ", constraint=false, weight=1]; navigationAutomat:p_nav_delpath:e -> deliveryEditorAutomat:in0:n [color="#ffb25a", fontcolor="#ffb25a", tooltip="navigationAutomat → deliveryEditorAutomat (restore draft path)", label=" restore draft path ", weight=3]; companyAutomat:p_comp_usr:w -> chatAutomat:in2:n [color="#66b3ff", fontcolor="#66b3ff", tooltip="companyAutomat → chatAutomat (chatDrawerWidth)", label=" chatDrawerWidth ", weight=3]; helpAutomat:p_help_active:e -> navigationAutomat:in1:n [color="#5aa7ff", fontcolor="#5aa7ff", tooltip="helpAutomat → navigationAutomat (route-contextual help)", label=" route-contextual help ", weight=3]; categoryAutomat:p_cat_categories:ne -> categoryAutomat:in1:n [color="#6bdf9a", fontcolor="#6bdf9a", tooltip="categoryAutomat → categoryAutomat (nested tree hierarchy)", label=" nested tree hierarchy ", weight=3]; artikelAutomat:p_art_set:ne -> artikelAutomat:in0:n [color="#f5c15c", fontcolor="#f5c15c", tooltip="artikelAutomat → artikelAutomat (variants & parent SKU)", label=" variants & parent SKU ", weight=3]; chatAutomat:p_chat_msg:nw -> chatAutomat:in1:n [color="#ff7fc2", fontcolor="#ff7fc2", tooltip="chatAutomat → chatAutomat (stream delta appends)", label=" stream delta appends ", weight=3]; }