Architecture

This page shows the panel at the levels of the C4 model: the system context, the containers and the components of the web application. Two model-view-controller diagrams then show which view classes read which data and render which templates.

The system context and container diagrams are written by hand: they show the deployment boundaries, which panel/nix/ and core/ define. The component and model-view-controller diagrams are generated from the sources in panel/src/ when the documentation builds, by panel/nix/architecture-diagrams.py. A new module, route, view or template shows up there with no edit to this page.

In all diagrams, a dashed border marks a system or container outside the scope of the diagram. Click a diagram to show it at its full size.

System context

flowchart TB
  operator(["<b>Operator</b><br/>[Person]<br/>Runs Fediversity applications<br/>for their organization."])
  admin(["<b>Hosting provider admin</b><br/>[Person]<br/>Manages operator accounts."])
  panel["<b>Fediversity Panel</b><br/>[Software system]<br/>Lets operators configure,<br/>deploy and remove applications."]
  api["<b>Fediversity API</b><br/>[Software system]<br/>Serves the configuration schema,<br/>queues and runs deployments,<br/>publishes their state."]
  idp["<b>Identity provider</b><br/>[Software system: OpenID Connect]<br/>Authenticates operators."]
  openbao["<b>OpenBao</b><br/>[Software system]<br/>Holds and rotates secrets."]
  hosting["<b>Hosting infrastructure</b><br/>[Software system]<br/>Runs the deployed applications."]
  operator -->|"configures and deploys<br/>applications, HTTPS"| panel
  admin -->|"manages accounts, HTTPS"| panel
  operator -.->|"signs in"| idp
  panel -->|"signs operators in"| idp
  panel -->|"submits configurations,<br/>reads deployment state"| api
  api -->|"asks to authorize operators"| panel
  panel -->|"reads database credentials<br/>and the callback token"| openbao
  api -->|"deploys applications"| hosting
  class api,idp,openbao,hosting external
  classDef external stroke-dasharray: 5 5

Containers

The panel is one Django application. The database is PostgreSQL in a Fediversity deployment, where OpenBao rotates its credentials, and SQLite when the NixOS module of the panel runs on its own.

flowchart TB
  operator(["<b>Operator</b><br/>[Person]"])
  admin(["<b>Hosting provider admin</b><br/>[Person]"])
  subgraph panel ["Fediversity Panel [Software system]"]
    browser["<b>Web browser</b><br/>[Container: HTML, htmx, forms island]<br/>Renders the pages, the configuration<br/>form and live deployment state."]
    nginx["<b>Reverse proxy</b><br/>[Container: nginx]<br/>Terminates TLS, serves static files,<br/>limits the rate of password logins."]
    web["<b>Web application</b><br/>[Container: Django on uvicorn, ASGI]<br/>Serves the pages, mints bearer tokens,<br/>authorizes event subscriptions."]
    db[("<b>Database</b><br/>[Container: PostgreSQL, or SQLite standalone]<br/>Users, deployments, operator settings.")]
  end
  subgraph apisystem ["Fediversity API [Software system]"]
    api["<b>API</b><br/>[Container: HTTP]<br/>Configuration schema,<br/>deployments, audit events."]
    centrifugo["<b>Centrifugo</b><br/>[Container: pub/sub]<br/>Pushes deployment state<br/>to browsers."]
  end
  idp["<b>Identity provider</b><br/>[Software system: OpenID Connect]"]
  openbao["<b>OpenBao</b><br/>[Software system]"]
  operator -->|uses| browser
  admin -->|"uses /admin/"| browser
  browser -->|HTTPS| nginx
  nginx -->|"HTTP, ASGI"| web
  web -->|"reads and writes, SQL"| db
  web -->|"HTTP, through api_client"| api
  web -->|"OpenID Connect"| idp
  browser -->|"HTTPS, bearer token"| api
  browser -->|"WebSocket, events.domain"| centrifugo
  centrifugo -->|"connect, subscribe and<br/>publish callbacks"| nginx
  api -->|"authorization callback"| nginx
  openbao -.->|"database credentials,<br/>callback token"| web
  class api,centrifugo,idp,openbao external
  classDef external stroke-dasharray: 5 5

Components

The components of the web application are the modules of the panel package. An arrow is an import, or a module path in a setting, and its label names what the module uses. A dotted arrow leaves the web application. A line with no arrowhead is a call from a system that the panel also calls, labelled with the routes that the system calls.

flowchart TB
  subgraph web ["Web application [Container: Django on uvicorn]"]
    m_admin["<b>admin</b><br/>[Component: Python module]<br/>The Django admin pages, where an<br/>admin manages the accounts."]
    m_api_client["<b>api_client</b><br/>[Component: Python module]<br/>Thin facade over the generated<br/>fediversity_api_client OpenAPI<br/>client."]
    m_asgi["<b>asgi</b><br/>[Component: Python module]<br/>ASGI config for panel project."]
    m_context_processors["<b>context_processors</b><br/>[Component: Python module]<br/>Template context processors."]
    m_forms["<b>forms</b><br/>[Component: Python module]<br/>The forms the deployment pages post."]
    m_models["<b>models</b><br/>[Component: Python module]<br/>The data the panel stores: the<br/>deployments and the settings of each<br/>operator."]
    m_oidc["<b>oidc</b><br/>[Component: Python module]<br/>Single sign-on (OpenID Connect)<br/>settings for the panel."]
    m_settings["<b>settings</b><br/>[Component: Python module]<br/>Django settings for panel project."]
    m_templatetags_custom_tags["<b>templatetags.custom_tags</b><br/>[Component: Python module]<br/>Template tags the pages load."]
    m_tokens["<b>tokens</b><br/>[Component: Python module]<br/>Bearer tokens the browser mints to<br/>call api/'s HTTP surface directly."]
    m_urls["<b>urls</b><br/>[Component: Python module]<br/>URL configuration for panel project."]
    m_views["<b>views</b><br/>[Component: Python module]<br/>The view classes that serve the<br/>pages and the endpoints of the<br/>panel."]
    m_wsgi["<b>wsgi</b><br/>[Component: Python module]<br/>WSGI config for panel project."]
    t_templates["<b>templates</b><br/>[Component: Django templates]<br/>15 templates"]
  end
  x_api["<b>Fediversity API</b><br/>[Software system]"]
  class x_api external
  x_browser["<b>Web browser</b><br/>[Container: HTML, htmx, forms island]"]
  class x_browser external
  x_centrifugo["<b>Centrifugo</b><br/>[Container of the Fediversity API]"]
  class x_centrifugo external
  x_database[("<b>Database</b><br/>[Container: PostgreSQL, or SQLite standalone]")]
  class x_database external
  x_idp["<b>Identity provider</b><br/>[Software system: OpenID Connect]"]
  class x_idp external
  x_nginx["<b>Reverse proxy</b><br/>[Container: nginx]"]
  class x_nginx external
  x_browser -->|HTTPS| x_nginx
  x_nginx -->|HTTP, ASGI| m_asgi
  x_nginx ---|"Fediversity API calls api_authz"| x_api
  x_centrifugo -->|"centrifugo_connect, centrifugo_publish, centrifugo_subscribe"| x_nginx
  m_admin -->|"DeploymentDestroyError"| m_models
  m_admin -.->|"User, transaction"| x_database
  m_api_client -.->|"AuditEventListResponse, AuthenticatedClient, Client, +22"| x_api
  m_asgi --> m_settings
  m_context_processors -->|"OperatorSettings"| m_models
  m_forms -->|"Deployment, OperatorSettings"| m_models
  m_models -->|"OUTAGE_ERRORS, deployment_delete_call"| m_api_client
  m_models -->|"mint"| m_tokens
  m_models -.->|"UnexpectedStatus"| x_api
  m_models -.->|"User, models, pre_delete"| x_database
  m_oidc -.->|"DEFAULT_AUTH_PIPELINE"| x_idp
  m_settings -->|"centrifugo, oidc, update_notice"| m_context_processors
  m_settings -->|"OIDC_BACKEND, enabled, social_auth_settings"| m_oidc
  m_settings --> m_urls
  m_settings -->|"application"| m_wsgi
  m_urls -->|"AccountDetail, AccountHistory, ApiToken, +22"| m_views
  m_views -->|"OUTAGE_ERRORS, audit_event_list_call, configuration_sections_call, +7"| m_api_client
  m_views -->|"DeploymentModelForm, OperatorSettingsForm, UpdatePolicyForm"| m_forms
  m_views -->|"Deployment, OperatorSettings"| m_models
  m_views -->|"mint, mint_reconcile, verify, +1"| m_tokens
  m_views -.->|"UnexpectedStatus"| x_api
  m_views -.->|"User, UserSocialAuth"| x_database
  m_wsgi --> m_settings
  m_views -->|renders| t_templates
  t_templates -->|loads| m_templatetags_custom_tags
  m_urls -->|"admin.site.urls, autodiscover"| m_admin
  classDef external stroke-dasharray: 5 5

Model-view-controller

Django calls this structure model-template-view: the "view" of Django is the controller here, and its templates are the view. The model holds the Django models and the data of other systems that the panel reads: the API, through api_client, and the bearer tokens of tokens.

Pages

The view classes that render a template. A dotted arrow from a template is a form or a script that sends a request to a controller.

flowchart LR
  subgraph view ["View: templates"]
    t_account_detail_html["<b>account_detail.html</b><br/>scripts: update_policy.js,<br/>api_token.js, api_token_copy.js"]
    t_account_history_html["<b>account_history.html</b><br/>scripts: relative_time.js"]
    t_base_html["<b>base.html</b><br/>scripts: htmx.min.js, notice.js,<br/>logo_fallback.js, update_notice.js,<br/>theme.js"]
    t_deployment_form_html["<b>deployment_form.html</b><br/>scripts: centrifuge.js,<br/>centrifuge_session.js, api_token.js,<br/>deployment_delete.js,<br/>deployment_submit.js,<br/>migration_export.js,<br/>deployment_action.js,<br/>update_policy.js, relative_time.js,<br/>forms-island.js"]
    t_deployment_list_html["<b>deployment_list.html</b><br/>scripts: api_token.js,<br/>migration_import.js,<br/>relative_time.js, centrifuge.js,<br/>centrifuge_session.js,<br/>deployment_delete.js,<br/>migration_export.js"]
    t_deployment_sbom_html["<b>deployment_sbom.html</b>"]
    t_deployment_section_form_html["<b>deployment_section_form.html</b><br/>scripts: centrifuge.js,<br/>centrifuge_session.js, api_token.js,<br/>deployment_delete.js,<br/>deployment_submit.js,<br/>forms-island.js"]
    t_index_html["<b>index.html</b>"]
    t_instance_list_html["<b>instance_list.html</b>"]
    t_partials__api_unreachable_html["<b>partials/_api_unreachable.html</b>"]
    t_partials__deployment_actions_html["<b>partials/_deployment_actions.html</b>"]
    t_partials__island_skeleton_html["<b>partials/_island_skeleton.html</b>"]
    t_partials__messages_html["<b>partials/_messages.html</b>"]
    t_partials__update_policy_fields_html["<b>partials/_update_policy_fields.html</b>"]
    t_registration_login_html["<b>registration/login.html</b>"]
  end
  subgraph controller ["Controller: view classes"]
    inc_admin_site_urls["<b>admin.site.urls</b><br/>[included URLconf]<br/>/admin/"]
    c_Index["<b>Index</b><br/>[page]<br/>/"]
    inc_django_contrib_auth_urls["<b>django.contrib.auth.urls</b><br/>[included URLconf]<br/>/"]
    inc_social_django_urls["<b>social_django.urls</b><br/>[included URLconf]<br/>/oauth/"]
    c_AccountDetail["<b>AccountDetail</b><br/>[page]<br/>/account/"]
    c_AccountHistory["<b>AccountHistory</b><br/>[page]<br/>/account/history/"]
    c_InstanceList["<b>InstanceList</b><br/>[page]<br/>/instances/"]
    c_DeploymentList["<b>DeploymentList</b><br/>[page]<br/>/deployments/"]
    c_DeploymentForm["<b>DeploymentForm</b><br/>[page]<br/>/deployments/{pk}/"]
    c_DeploymentSbom["<b>DeploymentSbom</b><br/>[page]<br/>/deployments/{pk}/sbom/"]
    c_DeploymentSectionForm["<b>DeploymentSectionForm</b><br/>[page]<br/>/deployments/{pk}/section/{section}/"]
    inc_debug_toolbar_urls["<b>debug_toolbar.urls</b><br/>[included URLconf, only if settings.DEBUG]<br/>/debug/"]
    f_DeploymentModelForm["<b>DeploymentModelForm</b><br/>[form]"]
  end
  subgraph model ["Model"]
    model_Deployment[("<b>Deployment</b><br/>[Django model]")]
    model_OperatorSettings[("<b>OperatorSettings</b><br/>[Django model]")]
    model_User[("<b>User</b><br/>[Django model]")]
    model_UserSocialAuth[("<b>UserSocialAuth</b><br/>[Django model]")]
    subgraph api_group ["api/, through api_client"]
      api_audit_event_list_call["<b>audit_event_list_call</b>"]
      api_configuration_sections_call["<b>configuration_sections_call</b>"]
      api_deployment_get_status["<b>deployment_get_status</b>"]
      api_domain_list_call["<b>domain_list_call</b>"]
      api_sbom_list_call["<b>sbom_list_call</b>"]
    end
    subgraph tokens_group ["tokens"]
      tokens_mint["<b>mint</b>"]
    end
  end
  t_index_html ---|rendered by| c_Index
  t_registration_login_html ---|rendered by| inc_django_contrib_auth_urls
  t_account_detail_html ---|rendered by| c_AccountDetail
  c_AccountDetail --> model_OperatorSettings
  c_AccountDetail --> model_User
  t_account_history_html ---|rendered by| c_AccountHistory
  c_AccountHistory --> model_Deployment
  c_AccountHistory --> model_User
  c_AccountHistory --> model_UserSocialAuth
  c_AccountHistory --> api_audit_event_list_call
  c_AccountHistory --> tokens_mint
  t_instance_list_html ---|rendered by| c_InstanceList
  c_InstanceList --> model_Deployment
  c_InstanceList --> api_configuration_sections_call
  c_InstanceList --> api_deployment_get_status
  c_InstanceList --> tokens_mint
  t_deployment_list_html ---|rendered by| c_DeploymentList
  c_DeploymentList --> model_Deployment
  t_deployment_form_html ---|rendered by| c_DeploymentForm
  c_DeploymentForm -->|validates with| f_DeploymentModelForm
  c_DeploymentForm --> model_Deployment
  c_DeploymentForm --> model_OperatorSettings
  c_DeploymentForm --> model_User
  c_DeploymentForm --> model_UserSocialAuth
  c_DeploymentForm --> api_deployment_get_status
  c_DeploymentForm --> api_domain_list_call
  c_DeploymentForm --> tokens_mint
  t_deployment_sbom_html ---|rendered by| c_DeploymentSbom
  c_DeploymentSbom --> model_Deployment
  c_DeploymentSbom --> api_sbom_list_call
  c_DeploymentSbom --> tokens_mint
  t_deployment_section_form_html ---|rendered by| c_DeploymentSectionForm
  c_DeploymentSectionForm -->|validates with| f_DeploymentModelForm
  c_DeploymentSectionForm --> model_Deployment
  c_DeploymentSectionForm --> model_OperatorSettings
  c_DeploymentSectionForm --> model_User
  c_DeploymentSectionForm --> model_UserSocialAuth
  c_DeploymentSectionForm --> api_configuration_sections_call
  c_DeploymentSectionForm --> api_deployment_get_status
  c_DeploymentSectionForm --> api_domain_list_call
  c_DeploymentSectionForm --> tokens_mint
  t_account_detail_html -.->|submits to| c_AccountDetail
  t_account_history_html -.->|submits to| c_AccountHistory
  t_base_html -.->|submits to| inc_django_contrib_auth_urls
  t_deployment_form_html -.->|submits to| c_DeploymentForm
  t_deployment_section_form_html -.->|submits to| c_DeploymentSectionForm
  t_registration_login_html -.->|submits to| inc_social_django_urls
  t_partials__update_policy_fields_html ---|included by| t_account_detail_html
  t_base_html -.-|extended by| t_account_detail_html
  t_base_html -.-|extended by| t_account_history_html
  t_partials__messages_html ---|included by| t_base_html
  t_partials__api_unreachable_html ---|included by| t_deployment_form_html
  t_partials__island_skeleton_html ---|included by| t_deployment_form_html
  t_partials__deployment_actions_html ---|included by| t_deployment_form_html
  t_partials__update_policy_fields_html ---|included by| t_deployment_form_html
  t_base_html -.-|extended by| t_deployment_form_html
  t_base_html -.-|extended by| t_deployment_list_html
  t_base_html -.-|extended by| t_deployment_sbom_html
  t_partials__api_unreachable_html ---|included by| t_deployment_section_form_html
  t_partials__island_skeleton_html ---|included by| t_deployment_section_form_html
  t_partials__deployment_actions_html ---|included by| t_deployment_section_form_html
  t_base_html -.-|extended by| t_deployment_section_form_html
  t_base_html -.-|extended by| t_index_html
  t_partials__api_unreachable_html ---|included by| t_instance_list_html
  t_base_html -.-|extended by| t_instance_list_html
  t_base_html -.-|extended by| t_registration_login_html
  f_DeploymentModelForm -->|binds| model_Deployment
  classDef external stroke-dasharray: 5 5

Endpoints

The view classes that return JSON, a redirect or a plain response, and what calls them: the scripts and templates of the pages, and the systems outside the panel.

flowchart LR
  subgraph callers ["Callers"]
    t_base_html["<b>base.html</b><br/>[template]"]
    t_deployment_form_html["<b>deployment_form.html</b><br/>[template]"]
    t_deployment_list_html["<b>deployment_list.html</b><br/>[template]"]
    t_partials__deployment_actions_html["<b>partials/_deployment_actions.html</b><br/>[template]"]
    js_api_token_js["<b>api_token.js</b><br/>[script]"]
    x_api["<b>Fediversity API</b><br/>[Software system]"]
    class x_api external
    x_centrifugo["<b>Centrifugo</b><br/>[Container of the Fediversity API]"]
    class x_centrifugo external
  end
  subgraph controller ["Controller: view classes"]
    c_UpdatesSeen["<b>UpdatesSeen</b><br/>[plain]<br/>/account/updates-seen/"]
    c_DeploymentCreate["<b>DeploymentCreate</b><br/>[redirect]<br/>/deployments/new/"]
    c_DeploymentDuplicate["<b>DeploymentDuplicate</b><br/>[redirect]<br/>/deployments/{pk}/duplicate/"]
    c_DeploymentDestroyConfirm["<b>DeploymentDestroyConfirm</b><br/>[plain]<br/>/deployments/{pk}/delete/confirm/"]
    c_DeploymentReconcile["<b>DeploymentReconcile</b><br/>[plain]<br/>/deployments/{pk}/delete/reconcile/"]
    c_DeploymentStateProxy["<b>DeploymentStateProxy</b><br/>[JSON]<br/>/deployments/{pk}/state/"]
    c_DeploymentSbomDownload["<b>DeploymentSbomDownload</b><br/>[JSON, plain]<br/>/deployments/{pk}/sbom/{node}/"]
    c_DeploymentUpdatePolicy["<b>DeploymentUpdatePolicy</b><br/>[redirect]<br/>/deployments/{pk}/update-policy/"]
    c_DeploymentDomainClaim["<b>DeploymentDomainClaim</b><br/>[redirect]<br/>/deployments/{pk}/domain-claim/"]
    r__deployments__uuid_pk___slug_section__["<b>RedirectView to deployment_section_form</b><br/>[redirect]<br/>/deployments/{pk}/{section}/"]
    c_ApiToken["<b>ApiToken</b><br/>[JSON]<br/>/api/token/"]
    c_ReconcileToken["<b>ReconcileToken</b><br/>[JSON]<br/>/api/reconcile-token/{pk}/"]
    c_DeploymentListProxy["<b>DeploymentListProxy</b><br/>[JSON]<br/>/api/deployments/"]
    c_UpdateNotice["<b>UpdateNotice</b><br/>[JSON]<br/>/api/update-notice/"]
    c_AuthzCallback["<b>AuthzCallback</b><br/>[JSON, plain]<br/>/api/authz/"]
    c_CentrifugoConnect["<b>CentrifugoConnect</b><br/>[JSON]<br/>/api/centrifugo/connect/"]
    c_CentrifugoSubscribe["<b>CentrifugoSubscribe</b><br/>[JSON, plain]<br/>/api/centrifugo/subscribe/"]
    c_CentrifugoPublish["<b>CentrifugoPublish</b><br/>[JSON]<br/>/api/centrifugo/publish/"]
  end
  subgraph model ["Model"]
    model_Deployment[("<b>Deployment</b><br/>[Django model]")]
    model_OperatorSettings[("<b>OperatorSettings</b><br/>[Django model]")]
    model_User[("<b>User</b><br/>[Django model]")]
    model_UserSocialAuth[("<b>UserSocialAuth</b><br/>[Django model]")]
    subgraph api_group ["api/, through api_client"]
      api_deployment_get_status["<b>deployment_get_status</b>"]
      api_deployment_list_call["<b>deployment_list_call</b>"]
      api_deployment_update_policy_call["<b>deployment_update_policy_call</b>"]
      api_domain_claim_call["<b>domain_claim_call</b>"]
      api_sbom_get_call["<b>sbom_get_call</b>"]
    end
    subgraph tokens_group ["tokens"]
      tokens_mint["<b>mint</b>"]
      tokens_mint_reconcile["<b>mint_reconcile</b>"]
      tokens_verify["<b>verify</b>"]
      tokens_verify_reconcile["<b>verify_reconcile</b>"]
    end
  end
  c_DeploymentSectionForm["<b>DeploymentSectionForm</b><br/>[page]<br/>/deployments/{pk}/section/{section}/"]
  c_UpdatesSeen --> model_OperatorSettings
  c_DeploymentCreate --> model_Deployment
  c_DeploymentDuplicate --> model_Deployment
  c_DeploymentDestroyConfirm --> model_Deployment
  c_DeploymentReconcile --> model_Deployment
  c_DeploymentReconcile --> tokens_verify_reconcile
  c_DeploymentStateProxy --> model_Deployment
  c_DeploymentStateProxy --> api_deployment_get_status
  c_DeploymentStateProxy --> tokens_mint
  c_DeploymentSbomDownload --> model_Deployment
  c_DeploymentSbomDownload --> api_sbom_get_call
  c_DeploymentSbomDownload --> tokens_mint
  c_DeploymentUpdatePolicy --> model_Deployment
  c_DeploymentUpdatePolicy --> api_deployment_update_policy_call
  c_DeploymentUpdatePolicy --> tokens_mint
  c_DeploymentDomainClaim --> model_Deployment
  c_DeploymentDomainClaim --> api_domain_claim_call
  c_DeploymentDomainClaim --> tokens_mint
  c_ApiToken --> tokens_mint
  c_ReconcileToken --> model_Deployment
  c_ReconcileToken --> tokens_mint_reconcile
  c_DeploymentListProxy --> model_Deployment
  c_DeploymentListProxy --> api_deployment_list_call
  c_DeploymentListProxy --> tokens_mint
  c_UpdateNotice --> model_Deployment
  c_UpdateNotice --> model_OperatorSettings
  c_UpdateNotice --> api_deployment_list_call
  c_UpdateNotice --> tokens_mint
  c_AuthzCallback --> model_Deployment
  c_AuthzCallback --> model_User
  c_AuthzCallback --> model_UserSocialAuth
  c_AuthzCallback --> tokens_verify
  c_CentrifugoSubscribe --> model_Deployment
  t_base_html -.->|calls| c_UpdateNotice
  t_base_html -.->|calls| c_UpdatesSeen
  t_deployment_form_html -.->|calls| c_DeploymentDomainClaim
  t_deployment_form_html -.->|calls| c_DeploymentUpdatePolicy
  t_deployment_list_html -.->|calls| c_DeploymentCreate
  t_deployment_list_html -.->|calls| c_DeploymentDestroyConfirm
  t_deployment_list_html -.->|calls| c_DeploymentDuplicate
  t_deployment_list_html -.->|calls| c_DeploymentStateProxy
  t_deployment_list_html -.->|calls| c_ReconcileToken
  t_partials__deployment_actions_html -.->|calls| c_DeploymentDestroyConfirm
  t_partials__deployment_actions_html -.->|calls| c_DeploymentStateProxy
  t_partials__deployment_actions_html -.->|calls| c_ReconcileToken
  js_api_token_js -.->|fetches| c_ApiToken
  x_api -.->|calls| c_AuthzCallback
  x_centrifugo -.->|calls| c_CentrifugoConnect
  x_centrifugo -.->|calls| c_CentrifugoSubscribe
  x_centrifugo -.->|calls| c_CentrifugoPublish
  r__deployments__uuid_pk___slug_section__ -.->|redirects to| c_DeploymentSectionForm
  classDef external stroke-dasharray: 5 5

Notation

The C4 diagrams on this page are Mermaid flowcharts in the C4 style, not the C4Context, C4Container and C4Component diagram types of Mermaid. Those types draw with fixed colors, so they ignore the light and dark themes of this site, and they place elements in fixed rows rather than by their relations. Change to them when both of these are true:

  • They take their colors from the theme variables of Mermaid, so they follow the theme of the site, as flowcharts do.
  • Mermaid no longer marks them as experimental, and their layout keeps a diagram of this size readable without manual UpdateLayoutConfig tuning.

The generator then writes Component, Container_Ext and Rel elements in place of flowchart nodes and edges; the analysis of the sources stays the same.