Skip to content

Module Model and Manifests

James Daley edited this page Apr 25, 2026 · 2 revisions

Module Model and Manifests

Every module has two contracts: a Swift type contract and a JSON manifest contract. Both must agree on identity, type, version, and entry point.

Module Type Model

classDiagram
    class ForsettiModule {
      +descriptor: ModuleDescriptor
      +manifest: ModuleManifest
      +start(context)
      +stop(context)
    }
    class ForsettiUIModule {
      +uiContributions: UIContributions
    }
    class ForsettiAppModule
    ForsettiModule <|-- ForsettiUIModule
    ForsettiUIModule <|-- ForsettiAppModule
Loading
Module Type Protocol Purpose
service ForsettiModule Background behavior, domain services, sync, telemetry, data preparation, and non-visual feature support.
ui ForsettiUIModule A feature UI module with toolbar items, view injections, overlays, or other host-visible UI contributions.
app ForsettiAppModule A complete single-application module that carries the primary application UI.

Manifest Schema

{
  "schemaVersion": "1.0",
  "moduleID": "com.example.product.module",
  "displayName": "Example Module",
  "moduleVersion": {
    "major": 1,
    "minor": 0,
    "patch": 0
  },
  "moduleType": "ui",
  "supportedPlatforms": ["iOS", "macOS"],
  "minForsettiVersion": {
    "major": 0,
    "minor": 1,
    "patch": 0
  },
  "maxForsettiVersion": null,
  "capabilitiesRequested": ["toolbar_items", "view_injection"],
  "iapProductID": null,
  "entryPoint": "ExampleModule"
}
Field Required Notes
schemaVersion Yes Current supported value is 1.0.
moduleID Yes Stable unique ID. Duplicate IDs fail discovery.
displayName Yes Human-readable module name.
moduleVersion Yes Semantic version object with major, minor, and patch.
moduleType Yes service, ui, or app.
supportedPlatforms Yes One or more of iOS and macOS.
minForsettiVersion Yes Minimum runtime version required.
maxForsettiVersion No Optional upper bound.
capabilitiesRequested Yes Capabilities requested before activation.
iapProductID No Product identifier for paid/locked modules.
entryPoint Yes Registry key used to create the module instance.

Authoring Workflow

flowchart TD
    A["Choose module type"] --> B["Create Swift module class"]
    B --> C["Define descriptor"]
    C --> D["Create manifest JSON"]
    D --> E["Keep moduleID, moduleType, version, and entryPoint aligned"]
    E --> F["Register entryPoint in ModuleRegistry"]
    F --> G["Add manifest to Resources/ForsettiManifests"]
    G --> H["Run tests and guardrails"]
Loading

Registry Contract

let registry = ModuleRegistry()
registry.register(entryPoint: ExampleModule.Constants.entryPoint) {
    ExampleModule()
}

The manifest entryPoint must match the registry key. A discovered manifest without a matching registry factory cannot activate.

Manifest Validation Logic

flowchart LR
    JSON["JSON file"] --> Shape{"Looks like manifest?"}
    Shape -- no in fallback mode --> Skip["Ignore file"]
    Shape -- yes --> Decode["Decode ModuleManifest"]
    Decode --> Required{"Required fields present?"}
    Required -- no --> Fail["validationFailed"]
    Required -- yes --> Duplicate{"moduleID already loaded?"}
    Duplicate -- yes --> Dup["duplicateModuleID"]
    Duplicate -- no --> Index["Index by moduleID"]
Loading

Strict directory loading fails invalid JSON immediately. Fallback discovery ignores JSON files that do not contain the manifest root keys.

Capability Values

Capability Raw Value Typical Use
networking networking Network requests through host-provided service.
storage storage Non-sensitive storage.
secureStorage secure_storage Sensitive data storage.
fileExport file_export Export files through host-approved destination.
cryptoUtilities crypto_utilities Cryptographic helper access.
telemetry telemetry Event tracking through host telemetry service.
routingOverlay routing_overlay Overlay route and pointer behavior.
uiThemeMask ui_theme_mask Reserved for framework shell; currently denied by compatibility checks.
toolbarItems toolbar_items Toolbar item contributions.
viewInjection view_injection Slot-based SwiftUI view injection.

Clone this wiki locally