Skip to content

Security Privacy and Reliability

James Daley edited this page Jun 18, 2026 · 3 revisions

Security, Privacy, and Reliability

Forsetti's security model is based on explicit capabilities, host-owned services, entitlement gates, registration records, runtime requirements, and bounded module communication.

Trust Boundary Map

flowchart LR
    Module["Module"] --> Context["ForsettiContext"]
    Context --> Services["Host-owned services"]
    Context --> EventBus["Event bus"]
    Context --> Logger["Logger"]
    Context --> Router["Overlay router"]
    Host["Host app"] --> Policy["Capability and entitlement policy"]
    Host --> Registration["RegistrationStore"]
    Policy --> Runtime["Runtime activation"]
    Registration --> Runtime
    Runtime --> Module
Loading

Modules are not trusted with arbitrary host access. They receive the capabilities and services the host chooses to expose.

Security Practices

Area Practice
Capabilities Request only the capabilities the module actually needs.
Runtime requirements Declare required I/O, UI IDs, data isolation, and provider roles before activation.
Registration records Treat manifest drift as a deployment signal, not as a recoverable runtime guess.
Entitlements Treat iapProductID as activation policy, not display state.
Services Resolve protocols from ForsettiContext; do not reach into host internals.
Secure storage Use KeychainSecureStorageService through default platform services for production. Keep InMemorySecureStorageService for explicit tests/debug wiring only.
File export Treat suggested filenames as untrusted input; LocalFileExportService sanitizes names and writes inside its configured directory.
Events Avoid sensitive payloads in broad framework events.
Logging Do not log secrets, purchase tokens, or user-sensitive data.

Privacy Boundaries

flowchart TD
    Event["Module event or telemetry"] --> Review{"Contains user-sensitive data?"}
    Review -- yes --> Minimize["Remove or minimize payload"]
    Review -- no --> Policy{"Host telemetry policy allows it?"}
    Minimize --> Policy
    Policy -- yes --> Track["Track through TelemetryService"]
    Policy -- no --> Drop["Do not emit"]
Loading

Telemetry is a host-owned decision. Modules should describe intent through service protocols and avoid embedding analytics vendors.

Performance and Reliability

Concern Guidance
Cold start Keep manifests small and module start(context:) fast.
Large module counts Prefer service modules for shared background work and keep UI module discovery deterministic.
Offline entitlements StoreKit can use local entitlement state; design paid modules to handle temporary refresh delays.
Activation failures Fail before start(context:) when registration, compatibility, entitlements, capabilities, or runtime requirements are invalid.
Deactivation Implement stop(context:) idempotently and release module-owned resources.
UI composition Keep view injection slots stable and avoid expensive work during surface rebuilds.

Reliability Flow

flowchart LR
    Manifest["Manifest"] --> Registration["Registration check"]
    Registration --> EarlyFail["Early activation failure"]
    Requirement["Runtime requirements"] --> EarlyFail
    Entitlement["Entitlement"] --> EarlyFail
    Registry["Registry"] --> Start["start(context)"]
    Start --> Success["Active module"]
    Start --> Failure["Rollback and log"]
    Success --> EntitlementChange["Entitlement change"]
    EntitlementChange --> Reconcile["Deactivate if no longer unlocked"]
Loading

Production Readiness Checklist

  • Capability list reviewed for each module.
  • Runtime requirements reviewed for service, UI, data isolation, and default-role dependencies.
  • Registration store behavior is verified for the app deployment model.
  • Entitlement provider is production-appropriate for the target platform.
  • Debug unlock providers are not used in release builds.
  • Sensitive services are host-owned and backed by production storage.
  • File export paths cannot escape the configured export directory.
  • Module start(context:) and stop(context:) are idempotent.
  • Logs avoid user-sensitive payloads.
  • Runtime failure paths have tests.

Clone this wiki locally