-
-
Notifications
You must be signed in to change notification settings - Fork 1
Architecture
Forsetti follows a multi-module single-application architecture. The production app owns one visible SwiftUI module and activates service/feature lifecycle modules behind the Forsetti runtime boundary.
The app uses Pattern B: one application target with multiple runtime modules.
flowchart TB
subgraph AppTarget["Forsetti app target"]
Entry["ForsettiApp"]
Root["ForsettiProductionRootView"]
Bootstrap["ForsettiRuntimeBootstrap"]
AppServices["ForsettiApplicationServices"]
UI["Retail UI module"]
Dashboard["DashboardView and workspace shell"]
FeatureViews["Feature SwiftUI workspaces"]
end
subgraph Runtime["Forsetti public framework boundary"]
Core["ForsettiCore"]
Platform["ForsettiPlatform"]
Manifests["ModuleManifest loader"]
Registry["ModuleRegistry factories"]
Manager["Runtime module manager"]
Services["ForsettiServiceContainer"]
end
subgraph External["External systems"]
Jamf["Jamf Pro API"]
Keychain["System Keychain"]
Files["App container files"]
Logs["Unified log"]
end
Entry --> Root --> Bootstrap
Bootstrap --> AppServices
Bootstrap --> Core
Bootstrap --> Platform
Bootstrap --> Manifests --> Registry --> Manager
Bootstrap --> Services
Manager --> UI --> Dashboard --> FeatureViews
AppServices --> Jamf
AppServices --> Keychain
AppServices --> Files
AppServices --> Logs
Forsetti is structured so dependencies flow from the app entry down into runtime, services, UI composition, and feature view models.
flowchart TD
AppEntry["App entry"] --> Bootstrap["Runtime bootstrap"]
Bootstrap --> PublicFramework["Forsetti public products"]
Bootstrap --> ServiceAggregate["App service aggregate"]
Bootstrap --> FactoryRegistry["Runtime module factories"]
FactoryRegistry --> UIModule["Single UI module"]
UIModule --> WorkspaceBuilders["Feature workspace builders"]
WorkspaceBuilders --> ViewModels["Feature view models"]
ViewModels --> ServiceFacades["App-owned service facades"]
FactoryRegistry --> LifecycleModules["Service and feature lifecycle modules"]
LifecycleModules --> ServiceFacades
Bad1["Feature -> app entry"] -. disallowed .-> AppEntry
Bad2["Feature -> unrelated feature"] -. disallowed .-> WorkspaceBuilders
Bad3["Service module -> primary UI"] -. disallowed .-> UIModule
Bad4["App -> framework internals"] -. disallowed .-> PublicFramework
| Path | Responsibility |
|---|---|
ForsettiApp/App |
App identity, SwiftUI app entry, production root view, runtime bootstrap, app service aggregate, and framework container. |
ForsettiApp/DesignSystem |
Theme, colors, typography, Metal-backed backgrounds, command activity bar, hardware visualization, and shared surface styles. |
ForsettiApp/Framework/Core |
App-local dashboard module contracts, module registry, sharing support, and common record rendering helpers. |
ForsettiApp/Framework/Networking |
Jamf API gateway, authentication service, request scope service, RSQL helpers, and URLSession tuning. |
ForsettiApp/Framework/Security |
Keychain-backed secure store and Jamf credential persistence. |
ForsettiApp/Framework/Diagnostics |
In-memory and persistent diagnostics model and export support. |
ForsettiApp/Framework/UI |
Dashboard shell, settings, diagnostics view, scanner input, platform compatibility, and support views. |
ForsettiApp/Modules |
App-owned feature workflows and feature-specific models, services, views, rendering, persistence, and tests. |
ForsettiApp/Resources/ForsettiManifests |
Runtime manifests loaded by the Forsetti public framework. |
ModulePackageTemplates |
App-owned package/template metadata for dashboard/import flows. These are not runtime manifests. |
ForsettiTests |
Unit, integration, model, parser, layout, runtime, diagnostics, security, and feature tests. |
The production runtime boundary is defined by these facts:
- The app links only the public
ForsettiCoreandForsettiPlatformpackage products. - Runtime manifests use the
com.forsetti.jamfpro.*namespace. - The app has exactly one production UI module:
com.forsetti.jamfpro.retail.ui. - Service and feature modules are lifecycle modules; they activate behind the UI and expose readiness, validation, diagnostics, and capability declarations.
- Feature SwiftUI views are still app-owned workspaces. The runtime module layer is the production activation and capability boundary.
flowchart LR
subgraph PrivateStores["Private module stores"]
UIS["forsetti-retail-ui"]
CS["forsetti-computer-search"]
MS["forsetti-mobile-device-search"]
ST["forsetti-support-technician"]
PS["forsetti-prestage-director"]
RP["forsetti-reports"]
DT["forsetti-deployment-tracker"]
PM["forsetti-permissions-matrix"]
end
subgraph SharedServices["Shared app services"]
Credentials["JamfCredentialsStore"]
Gateway["JamfAPIGateway"]
Diagnostics["DiagnosticsCenter"]
Packages["ModulePackageManager"]
end
PrivateStores --> SharedServices
Credentials --> Keychain["Keychain service com.ravenforge.forsetti"]
Gateway --> Jamf["Jamf Pro API"]
Diagnostics --> NDJSON["ForsettiDiagnostics/forsetti-diagnostics.ndjson"]
Diagnostics --> Unified["Unified log subsystem"]
Packages --> Disk["App container package store"]
The visible UI starts only after runtime boot succeeds. DashboardView receives ForsettiFrameworkContainer from ForsettiApplicationServices, renders the command center, and navigates into dashboard-facing feature modules through ModuleContext.
flowchart TD
Root["ForsettiProductionRootView"] -->|booting| Progress["ForsettiBootProgressView"]
Root -->|ready| Dashboard["DashboardView"]
Root -->|failed| Failure["ForsettiBootFailureView"]
Dashboard --> Rail["Navigation rail"]
Dashboard --> Header["Command center header"]
Dashboard --> Cards["Module cards"]
Dashboard --> Inspector["Tenant state and module mix"]
Dashboard --> Drawer["Diagnostics drawer"]
Cards --> ModuleRoot["module.makeRootView(context:)"]
ModuleRoot --> ViewModel["Feature view model"]
ViewModel --> Context["ModuleContext"]
Context --> API["JamfAPIGateway"]
Context --> Credentials["JamfCredentialsStore"]
Context --> Diagnostics["DiagnosticsReporting"]
| Target | Current setting |
|---|---|
| macOS deployment target | 14.0 |
| iOS deployment target | 26.0 |
| Bundle family | com.ravenforge.forsetti |
| Code signing in CI | Disabled for build/test commands with CODE_SIGNING_ALLOWED=NO
|
Some app UI files live under framework-named source folders, especially under ForsettiApp/Framework/UI. The current architecture treats these as app-owned UI composition files, not framework internals. The runtime boundary remains enforced through package linking, manifest loading, public framework APIs, and the production bootstrap.
Forsetti Jamf Pro documentation. Keep module IDs, build commands, and security behavior aligned with the repository source before changing this wiki.