Files
logos-basecamp/docs/spec.md

24 KiB

Logos Basecamp

Overall Description

Logos Basecamp is a desktop application shell for the Logos modular platform. It provides a unified graphical environment that manages two types of components: Logos Modules (Logos Modules managed by liblogos_core) and UI Apps (Qt plugins loaded directly by Basecamp that provide graphical interfaces). Together, these components deliver functionality like messaging, storage, wallets, and package management through a common navigation model.

The application is designed to:

  • Serve as a frontend for the Logos runtime (liblogos_core), managing Logos Module lifecycle via its C API
  • Host UI Apps as tabbed workspaces in a sidebar-and-content layout, with each app able to call Logos Modules for backend services
  • Provide a built-in package manager for installing, browsing, and removing both Logos Modules and UI Apps
  • Sandbox untrusted QML UI App content — restricting its network access, filesystem reach, and ability to load native code into the host process
  • Offer cross-platform distribution as a self-contained portable application

Definitions & Acronyms

Term Definition
Logos Module An independently developed plugin that implements PluginInterface and is managed by the Logos runtime (liblogos_core). Each module runs in its own isolated logos_host subprocess, communicates via the Logos API, and is authenticated with tokens. Examples: package_manager, capability_module, waku_module.
UI App A Qt plugin (C++ shared library or QML package) loaded directly by Basecamp into its own process. UI Apps provide a graphical widget displayed as a tab in the MDI workspace. They are managed entirely by Basecamp, not by liblogos. UI Apps may depend on Logos Modules for backend services. Examples: package_manager_ui.
MDI Multi-Document Interface — the tabbed content area where UI App windows are displayed
Sidebar The left-hand navigation panel listing available UI Apps, system views, and loaded modules
Section A named navigation entry in the sidebar; sections are typed as either "workspace" (apps) or "view" (system screens)
LGX Logos Package Format — the archive format used to distribute both Logos Modules and UI Apps
Module Directory A filesystem path scanned by liblogos for Logos Module shared libraries at startup
Plugin Directory A filesystem path scanned by Basecamp for UI App shared libraries or QML packages
Embedded Logos Modules or UI Apps bundled into the application at build time (read-only)
User-installed Logos Modules or UI Apps installed at runtime to a user-writable directory
Portable Build A self-contained build with no external dependency references, suitable for distribution
Dev Build A development build that references the Nix store for dependencies

Domain Model

Two Types of Components

Basecamp manages two fundamentally different types of components:

Logos Modules are process-isolated modules managed by the Logos runtime (liblogos_core). Each Logos Module runs in its own logos_host subprocess, communicates with other modules via the Logos API through the remote object registry, and is authenticated with UUID tokens. Basecamp does not load or host these modules itself — it delegates to liblogos_core via its C API. Examples include package_manager (manages installed packages), capability_module (handles authorization tokens), and waku_module (peer-to-peer networking). These modules have no UI of their own and run headlessly in the background providing services.

UI Apps are Qt plugins (either C++ shared libraries implementing IComponent, or QML packages) loaded directly by Basecamp into its own process using Qt's QPluginLoader or QQuickWidget. UI Apps are not managed by liblogos — Basecamp handles their full lifecycle: discovery, loading, widget creation, tab management, and unloading. UI Apps provide a graphical interface displayed as a tab in the MDI workspace. They typically depend on one or more Logos Modules for backend functionality — for example, package_manager_ui calls methods on the package_manager Logos Module via LogosAPI.

┌─────────────────────────────────────────────────────────────┐
│  Basecamp Process                                           │
│  ┌────────────────────────────────────┐                     │
│  │ Application Shell + Main UI        │                     │
│  │  ├─ Sidebar, MDI, system views     │                     │
│  │  └─ UI App: package_manager_ui ◄───┼── QPluginLoader     │
│  │                                    │   (in-process)       │
│  └────────────────────────────────────┘                     │
│  ┌────────────────────────────────────┐                     │
│  │ liblogos_core (linked library)     │                     │
│  │  ├─ Remote Object Registry         │                     │
│  │  └─ Module lifecycle C API         │                     │
│  └────────────┬───────────────────────┘                     │
│               │ IPC (local sockets)                         │
│         ┌─────┼─────────┬─────────┐                         │
│         ▼     ▼         ▼         ▼                         │
│  ┌──────────┐┌──────────┐┌──────────┐┌──────────┐          │
│  │logos_host││logos_host││logos_host││logos_host│           │
│  │pkg_mgr  ││capability││ waku    ││ storage │           │
│  └──────────┘└──────────┘└──────────┘└──────────┘          │
│  Logos Modules (separate processes, managed by liblogos)     │
└─────────────────────────────────────────────────────────────┘

Application Architecture

At a high level, Basecamp consists of:

Application Shell — The main window that initializes the Logos runtime (via liblogos_core), creates the navigation layout, and manages the application lifecycle (system tray, window state, platform-specific styling).

Main UI Plugin — A dynamically loaded Qt plugin that provides the full user interface: sidebar navigation, content area, module management views, and the MDI workspace. Separating the UI into a plugin allows the shell to remain minimal.

Backend — The logic layer (MainUIBackend) that coordinates both Logos Module and UI App state — it calls liblogos_core to manage Logos Modules, uses QPluginLoader to manage UI Apps, collects resource statistics, manages navigation sections, and communicates with the package manager for install/uninstall events.

MDI View — A tabbed workspace where each loaded UI App gets its own tab. Tabs can be opened, closed, and switched via the sidebar or the tab bar.

QML Bridge — A bridge that exposes Logos Module method calls to QML-based UI Apps, serializing results to JSON for consumption by the declarative UI layer. This is how UI Apps communicate with the backend Logos Modules they depend on.

Navigation Model

The sidebar organizes content into typed sections:

┌──────────────────────────────────────────────────────┐
│  Sidebar                    Content Area             │
│  ┌────────┐                ┌───────────────────────┐ │
│  │ Logo   │                │                       │ │
│  ├────────┤                │  MDI Workspace        │ │
│  │ App 1  │◄──workspace──► │  ┌─────┬─────┬─────┐ │ │
│  │ App 2  │                │  │Tab 1│Tab 2│Tab 3│ │ │
│  │ App 3  │                │  ├─────┴─────┴─────┤ │ │
│  │        │                │  │                  │ │ │
│  │        │                │  │  Active Plugin   │ │ │
│  │        │                │  │  Widget          │ │ │
│  ├────────┤                │  │                  │ │ │
│  │  ⌂     │◄──view───────► │  └──────────────────┘ │ │
│  │  ▣     │  Dashboard     │                       │ │
│  │  ⚙     │  Modules       │  OR                   │ │
│  └────────┘  Settings      │  Dashboard / Modules  │ │
│                            │  / Settings View      │ │
│                            └───────────────────────┘ │
└──────────────────────────────────────────────────────┘
  • Workspace sections appear in the upper sidebar and correspond to launchable apps. Clicking one opens (or focuses) the module in the MDI area.
  • View sections appear at the bottom of the sidebar and switch the content area to system screens (Dashboard, Modules, Settings).

Discovery

Basecamp discovers components from two separate sets of directories, reflecting the two component types:

Logos Module directories (managed by liblogos):

  1. Embedded modules directory — Read-only, bundled at build time, relative to the application binary.
  2. User modules directory — Writable, for runtime-installed modules. Platform-specific path under the user's application data directory.

At startup, liblogos_core scans these directories, extracts metadata from each plugin file, and populates the known-modules list. Logos Modules are not loaded until explicitly requested or declared as auto-load (e.g., package_manager).

UI App directories (managed by Basecamp):

  1. Embedded plugins directory — Read-only, bundled at build time.
  2. User plugins directory — Writable, for runtime-installed UI Apps.

Basecamp queries the package_manager Logos Module to discover installed UI Apps and their metadata (name, icon, QML or C++ type, dependencies).

Logos Module Lifecycle

Discovered ──► Loading ──► Running ──► Unloading ──► Discovered
   │              │            │            │
   │         Spawn         Active as     Terminate
   │         logos_host    background    host process
   │         process       service       + cleanup
   │         + auth token  (Logos API)
   │
   └── Metadata extracted, shown in Core Modules tab
  1. Discovery: liblogos scans module directories and extracts metadata. The module appears in the Core Modules tab as available but not loaded.
  2. Loading: liblogos spawns a dedicated logos_host process for the module, sends an authentication token via local socket, and waits for the module to register with the remote object registry.
  3. Running: The module provides services via the Logos API. Other modules and UI Apps can call its methods through LogosAPI. Resource usage (CPU, memory) is monitored by the runtime.
  4. Unloading: The host process is terminated, associated tokens are cleaned up, and the module returns to the discovered state.

UI App Lifecycle

Discovered ──► Loading ──► Running ──► Unloading ──► Discovered
   │              │            │            │
   │         Load plugin   Displayed    Destroy widget
   │         in-process    as MDI tab   + unload plugin
   │         + create      (user        + remove tab
   │           widget      interacts)
   │
   └── Metadata from package_manager, shown in UI Modules tab
  1. Discovery: Basecamp queries the package manager for installed UI Apps. They appear in the UI Modules tab.
  2. Loading: Basecamp loads the plugin directly into its own process. For C++ plugins, QPluginLoader loads the shared library and calls createWidget(LogosAPI*). For QML plugins, a QQuickWidget is created with a sandboxed QML engine (network-deny, filesystem-restricted, and barred from loading native code from the app's own directory — see QML App Sandboxing). If the UI App declares Logos Module dependencies, those are loaded first via logos_core_load_module_with_dependencies(). A new tab is added to the MDI workspace.
  3. Running: The UI App's widget is displayed in a tab. The user interacts with it. The app may call Logos Modules via the QML bridge or LogosAPI.
  4. Unloading: The tab is removed from the MDI area, the widget is destroyed, and the plugin is unloaded. Any Logos Module dependencies remain loaded (they may be shared with other apps).

Package Management Integration

Basecamp integrates with the package management system for installing both Logos Modules and UI Apps. An LGX package may contain either type — the package manager determines the correct installation directory based on the package contents:

  1. User clicks "Install LGX Package" in the Modules view, or uses the Package Manager UI App to browse the online catalog
  2. The package_manager Logos Module extracts the appropriate platform variant from the LGX archive
  3. Logos Module files are placed in the user modules directory; UI App files are placed in the user plugins directory
  4. The package manager emits an event (corePluginFileInstalled or uiPluginFileInstalled)
  5. Basecamp listens for these events and automatically refreshes the appropriate list — calling logos_core_refresh_modules() for Logos Modules, or re-querying the package manager for UI App metadata
  6. The user can then load the newly installed component from the Modules view

Features & Requirements

Component Management

UI App Management

  • List all discovered UI Apps with name, icon, and load status
  • Load a UI App by name, automatically loading any Logos Module dependencies first, and creating a tab in the MDI workspace
  • Unload a UI App, closing its tab and destroying its widget (Logos Module dependencies remain loaded)
  • Display app status in the sidebar

Logos Module Management

  • List all discovered Logos Modules with name, load status, and resource usage
  • Load a Logos Module by name (including its dependency tree), spawning an isolated logos_host process
  • Unload a Logos Module, terminating its host process
  • Display per-module CPU percentage and memory usage, updated every 2 seconds

Package Installation

  • Install Logos Modules and UI Apps from local LGX package files via the Modules view
  • Browse and download packages from the online catalog via the Package Manager UI App
  • Auto-discover newly installed components without restarting the application

Navigation

Sidebar

  • Display application logo and workspace app icons in the upper section
  • Display loaded UI App icons in the middle section with visual indicators for active state
  • Display system view icons (Dashboard, Modules, Settings) in the lower section
  • Clicking a workspace icon opens or focuses the corresponding UI App tab
  • Clicking a loaded app icon activates its tab
  • Right-click or close gesture on a loaded app unloads it and removes it from the workspace

Content Area

  • Stack-based layout switching between system views and the MDI workspace
  • MDI area with tab bar for managing multiple open UI App windows
  • Dashboard view for overview information
  • Modules view with tabs for UI Apps and Logos Modules
  • Settings view for application configuration

QML App Sandboxing

QML-based UI Apps (ui_qml modules) load directly into the Basecamp process, so an untrusted app is confined by a sandbox applied to its QML engine (QmlSandbox::configure). A ui_qml app is QML/JS only and must stay inside its own install directory; the sandbox enforces this on three fronts:

  • Network: a deny-all network access manager blocks all outgoing HTTP/HTTPS requests from sandboxed content; URL interception prevents navigation to external resources. UI Apps that need network access do so indirectly through Logos Modules (which run in their own process and are not sandboxed by Basecamp).
  • Filesystem: a URL interceptor resolves only qrc: URLs and local files under an allow-list of roots — the app's own dir, the vetted shared Logos QML modules, and Qt's own module dirs. Access to any other path is blocked.
  • Native code: the app's (untrusted) install dir is kept off the engine's native-plugin search path, and a qmldir under the app's own dir may not declare a native plugin. This closes a sandbox escape (F-008) in which a ui_qml app shipped a qmldir plugin directive plus a Qt plugin .so and had Qt dlopen() it into the host process — gaining native code execution that bypasses the network and filesystem restrictions. Qt loads native plugins without consulting the URL interceptor, so the interceptor instead rejects the qmldir that declares the plugin; vetted roots (Qt's own modules, which legitimately ship native plugins) are exempt. The sandbox-test Nix check guards this regression, and also covers the network and filesystem guarantees above (network deny for HTTP and file://, blocking of remote-scheme loads and out-of-root file reads, while files under the module's own dir and qrc: resources still resolve). It additionally loads an end-to-end adversarial fixture (tests/sandbox/evil_app/, the evil twin of counter_qml) that auto-fires every escape vector on load and asserts none get through.

Desktop Integration

  • System tray icon with minimize-to-tray and restore functionality
  • Platform-specific window styling (macOS native titlebar integration)
  • Application icon and branding

Distribution

  • Portable self-contained builds with no external dependency references
  • Linux distribution via AppImage (single executable)
  • macOS distribution via DMG with signed .app bundle
  • Embedded modules bundled at build time for out-of-box functionality

QML Inspector

  • Development tool for inspecting the running QML object tree
  • TCP-based server for remote inspection
  • Enabled by default in debug builds, disabled in release builds
  • Provides tools for UI testing and automation

User Journeys & Workflows

Application Startup

When the user launches Basecamp, the following happens from their perspective:

  1. The application window appears with a sidebar on the left and a content area on the right
  2. Built-in modules (package manager, capability module) are automatically loaded in the background
  3. The sidebar populates with available app icons and system view buttons (Dashboard, Modules, Settings)
  4. The content area shows the default view (Dashboard or last-active view)
  5. The user can immediately begin loading modules, installing packages, or launching apps

Browsing and Loading Components

  1. User clicks the Modules icon in the sidebar bottom section
  2. The Modules view opens with two tabs: UI Apps and Logos Modules
  3. The UI Apps tab lists all discovered UI Apps with name, icon, and load status
  4. The Logos Modules tab lists all discovered Logos Modules with name, load status, and resource usage (CPU/memory updated every 2 seconds for loaded modules)
  5. User clicks Load next to a component name
  6. For UI Apps: any required Logos Module dependencies are loaded first, then the app's widget appears as a new tab in the MDI workspace
  7. For Logos Modules: a logos_host process is spawned and the module starts providing services in the background
  8. User clicks Unload to stop a component

Installing a Package

  1. User navigates to the Modules view
  2. User clicks Install LGX Package
  3. A file picker dialog opens; user selects a .lgx file from their filesystem
  4. The package manager extracts the appropriate platform variant and installs files to the correct directory (modules dir for Logos Modules, plugins dir for UI Apps)
  5. The component list automatically refreshes to show the newly installed component
  6. User can now load the component as described above

Installing from the Online Catalog

  1. User loads the Package Manager UI app (or it is already loaded)
  2. The Package Manager UI appears as a tab in the MDI workspace
  3. User browses or searches the online catalog of available packages
  4. User selects a package and clicks download/install
  5. The package downloader fetches the .lgx file; the package manager installs it
  6. The Modules view refreshes to include the new component

Using a UI App

  1. User clicks an app icon in the sidebar's workspace section (top area)
  2. If the app is not yet loaded, it is loaded automatically — any required Logos Module dependencies are loaded first via liblogos
  3. The app's UI appears as a new tab in the MDI workspace
  4. User interacts with the app through its own interface (e.g., chat, file storage, wallet)
  5. The app may call Logos Modules in the background via LogosAPI (e.g., a chat UI App calls the waku_module Logos Module for networking)
  6. User can switch between multiple loaded apps via the sidebar icons or the MDI tab bar
  7. Closing a tab (via the tab bar close button or sidebar close gesture) unloads the UI App but leaves its Logos Module dependencies running

Monitoring Logos Module Resources

  1. User navigates to the Modules view → Logos Modules tab
  2. For each loaded Logos Module, CPU percentage and memory usage are displayed
  3. Statistics are polled from liblogos_core every 2 seconds
  4. If a module is consuming excessive resources, the user can unload it

Minimizing to System Tray

  1. User minimizes or closes the application window
  2. The application continues running in the system tray
  3. All loaded Logos Modules remain active in their host processes in the background
  4. Clicking the tray icon restores the window with all UI App tabs and state intact

Inter-Component Communication

UI Apps communicate with Logos Modules through the Logos API layer. Since UI Apps run in the Basecamp process and Logos Modules run in isolated logos_host processes, all communication crosses a process boundary via the Logos API:

UI App (QML)
    │
    ▼
LogosQmlBridge.callModule(module, method, args)
    │
    ▼
LogosAPI → Remote Object Registry → Logos Module host process
    │
    ▼
JSON result returned to QML
  • QML-based UI Apps use the QML bridge (logos.callModule(...)) to call any loaded Logos Module
  • C++ UI Apps use LogosAPI directly for inter-module calls
  • All Logos API calls are authenticated via the token-based system provided by liblogos_core
  • Results are serialized to JSON for QML consumption
  • Logos Modules can also call each other via the same Logos API mechanism, independent of Basecamp

Supported Platforms

  • Linux (x86_64, aarch64)
  • macOS (x86_64, aarch64)

Future Work

  • Module updates — Automatic detection and installation of module updates
  • Workspace persistence — Save and restore the set of loaded modules and tab layout across sessions
  • Theme customization — User-selectable color themes beyond the default design system
  • iOS support — Full iOS build and distribution pipeline (currently experimental)