FaceForge Core — Project Design Specification

Document Status: Design & Ideation
Scope: FaceForge Core
Last Updated: 2026-01-13
Version: v0.2.11

1. Source of Truth

This document is the authoritative design specification for FaceForge Core: what it must provide, what it intentionally avoids, and the interfaces that future work will build on.

FaceForge is designed to stay stable and boring at the center, while advanced functionality (recognition, training, integrations, rich visualizations, etc.) is delivered as optional plugins over the Core’s public APIs and job system.

Note: This specification describes desired behavior and interfaces. Where implementation details are not specified (or could vary), those areas are marked as TO-DO while preserving constraints and intent.

2. Project Philosophy and Vision

2.1 What is FaceForge?

FaceForge is a local-first, self-hosted Asset Management System (AMS) specialized for entities (real and fictional, human and non-human) and assets related to those entities (facial maps, voice samples, attributes, relationships, etc.).

It is envisioned as a desktop-managed local services bundle:

External tools (for example, ComfyUI or StashApp) must be able to query FaceForge and retrieve assets through a stable API without depending on the UI.

A common target environment includes very large local datasets. FaceForge is expected to operate primarily on local storage while remaining compatible with remote object storage systems (like Amazon S3, Google Cloud Storage, MEGA S4, MinIO, etc.).

2.2 The “boring core” philosophy

The Core provides stable foundations:

The Core does not own compute-heavy intelligence such as face recognition, force-directed graph rendering, or LoRA training. Those are delivered as plugins. FaceForge Core is the asset storage and management platform those capabilities connect to.

2.3 Key Design Principles

  1. Keep the center stable The Core stays small and dependable. New capabilities should plug in through stable interfaces rather than expanding Core scope.

  2. Transparent storage Assets must not be hidden inside opaque container volumes. Users must be able to see and manage where their data lives (local disks, NAS, remote storage, etc.). The user can control the application’s data storage broadly (running everything from a named folder path) or in a more modular way (e.g., separating database files from object storage).

  3. “Double-click” simplicity (cross-platform) The system must be runnable by non‑developer users via a single desktop launcher experience. Container runtimes (Docker, Podman, etc.) are explicitly out of scope for end‑user deployment. All required components are managed directly by the desktop shell application.

  4. Integration-first
    The Core is designed to serve downstream tools via a stable and well documented API. Documentation of the API is provided by OpenAPI/Swagger and kept in sync with the active implementation at all times.

3. What FaceForge Core Provides

The specific capabilities and features of FaceForge Core are categorized and defined as follows:

3.1 Central Metadata Engine

Note: The visual relationship graph UI is intentionally out of scope for the Core. The Core provides the data surface for relationship metadata; rendering and interaction will live in an official plugin (FFGraph).

3.2 Storage & Retrieval

First-run storage UX is desktop-managed:

Remote S3 endpoints remain a supported design target, but the initial list of “blessed” providers and setup UX can evolve over time.

3.3 Jobs & Logging

Design intent: Compute-heavy work happens out-of-process. The Core remains the job registry, API surface, and artifact store.

3.4 Plugin Foundations

Core is responsible for plugin discovery, registration, configuration, permissions, and versioning. Plugins must be able to:

3.5 Web-Based UI for all Core Features

4. Planned Official Plugins

These named plugins are upcoming design targets that the Core must accommodate naturally. The capabilities of these various plugins give a glimpse of the Core’s ultimate role and some potential intended use cases.

5. Project Non-Goals & Constraints

FaceForge Core does not directly:

The Core provides the platform surface those concerns plug into.

6. Core Architecture Baseline (Practical v1 Target)

This section describes a practical minimum baseline intended to be reliable and easy to run locally without containerization.

6.1 Runtime Layout (What Ships)

6.1.1 Desktop Shell Orchestrator - Tauri v2 desktop app (tray + updates + system popups) - Responsible for: - Starting/stopping/monitoring managed components (Core API service, local object storage, plugin runners) - Autostart at login (optional) - Presenting status/logs and opening the web UI

6.1.2 Core Service (Python 3.11/3.12 + FastAPI + Uvicorn) - Runs as a local HTTP API server: - /v1/... API - /docs and /redoc API playground - the web UI as static assets (one service, one port)

6.2 Database (SQLite)

Why SQLite (design reasoning): - Embeddable engine: no separate database service to install/manage; lifecycle is bound to the Core process. - Local-first reliability: single-file persistence with excellent durability; easy backups and restores. - Flexible fields without schema churn: admin-defined fields live in JSON; common fields can be indexed via generated columns. - Operational simplicity: fewer moving parts, fewer failure modes, and a smoother “double-click” experience.

6.3 S3-Compatible Object Storage (SeaweedFS)

Why SeaweedFS (design reasoning): - S3 compatibility for external tools without bundling MinIO (and its licensing/packaging concerns). - User transparency over where bucket data lives on disk. - Lightweight local services model appropriate for a self-hosted desktop-managed bundle.

6.4 Network and Security Defaults

6.5 Key Constraints

7. Data model (Core-owned, plugin-friendly)

This section defines the conceptual model. The physical schema is implementation work, but the invariants must hold.

7.1 Entities

Entities are the primary identity objects in the system (humans, characters, creatures, etc.).

7.2 Assets (Attachments)

Universal attachment model (files, models, documents, etc.).

7.3 Descriptors and Field Definitions

Two complementary concepts:

Design intent: - The system must support new descriptor keys being defined at any time. - Historic records are not required to have those keys. - Historic records may be updated later, without migrations or schema changes.

7.4 Jobs, Events, Relationships

8. Plugin Model (Contract-Level)

8.1 Plugin Types

A plugin may provide any combination of:

8.2 Plugin Manifest (Concept)

Each plugin ships with a manifest (example: plugin.json) containing:

8.3 Execution Model (Out-of-Process First)

Phase 1 (MVP): - plugins installed as folders inside a local install dir - Core loads manifests and exposes plugin metadata via API - Desktop shell starts/stops plugin runner processes as needed - Plugins communicate with Core via HTTP: - create jobs - stream logs/progress - upload artifacts (assets) and link them to entities - UI renders navigation based on manifest + enabled status

Phase 2 (later): - install from URL/local .whl/.zip - per-plugin virtualenvs (and potentially per-plugin Python versions) - signed bundles + marketplace

TO-DO: Bundle signing, distribution, sandboxing strategy, and permission enforcement depth need a separate design doc when in scope.

9. API Contract (Core + Plugin Friendly)

9.1 Versioning

9.2 Core Endpoints (Minimum)

9.2.1 Entities - GET /v1/entities - POST /v1/entities - GET /v1/entities/{entity_id} - PATCH /v1/entities/{entity_id} - DELETE /v1/entities/{entity_id} (soft delete recommended)

9.2.2 Descriptors - GET /v1/entities/{entity_id}/descriptors - POST /v1/entities/{entity_id}/descriptors - PATCH /v1/descriptors/{descriptor_id} - DELETE /v1/descriptors/{descriptor_id}

9.2.3 Field Definitions (Admin) - GET /v1/admin/field-defs - POST /v1/admin/field-defs - PATCH /v1/admin/field-defs/{field_key} - DELETE /v1/admin/field-defs/{field_key}

9.2.4 Assets / Attachments - POST /v1/assets/upload (multipart; supports companion _meta.json) - POST /v1/assets/bulk-import (directory import job; reads *_meta.json sidecars) - GET /v1/assets/{asset_id} - GET /v1/assets/{asset_id}/download (stream; must support HTTP range) - POST /v1/entities/{entity_id}/assets/{asset_id}/link - POST /v1/entities/{entity_id}/assets/{asset_id}/unlink

9.2.5 Relationships - GET /v1/relationships?entity_id=... - POST /v1/relationships - DELETE /v1/relationships/{relationship_id} - GET /v1/relation-types?query=sp

9.2.6 Jobs - POST /v1/jobs - GET /v1/jobs/{job_id} - GET /v1/jobs/{job_id}/log - POST /v1/jobs/{job_id}/cancel

9.2.7 Plugins - GET /v1/plugins - POST /v1/plugins/{id}/enable - POST /v1/plugins/{id}/disable - GET /v1/plugins/{id}/config - PUT /v1/plugins/{id}/config

9.3 Integration-Driven Core Requirements

Stable asset listing & download - GET /v1/entities/{entity_id}/assets?kind=model.lora - GET /v1/assets/{asset_id}/download supports large files and resumable downloads (HTTP range).

Bulk operations - POST /v1/entities/bulk-upsert (idempotent; external IDs supported) - POST /v1/jobs must support large inputs via stored “job input assets” (avoid giant JSON payloads)

TO-DO: The exact shape of external IDs and bulk-upsert conflict resolution rules require specification.

10. Storage & Path Configuration

All persistent data is stored in one or more user-controlled, user-defined directories.

FACEFORGE_HOME is the data directory root for FaceForge.

10.1 Required subfolders (created by Core)

On startup, Core ensures these subfolders exist under FACEFORGE_HOME:

10.2 Configurable vs non-configurable paths

Core supports path overrides via ${FACEFORGE_HOME}/config/core.json:

10.3 Core configuration file (current shape)

Core uses JSON configuration at ${FACEFORGE_HOME}/config/core.json. Current shape (v1):

11. Frontend Requirements (Core UI + plugin UI)

11.1 Core UI Coverage

The Core UI covers all Core features:

11.2 UI Delivery Model (Aligned with Desktop + Local Services)

Minimum UX expectations:

UI delivery is intentionally runtime-light:

12. Packaging and “Double-Click to Run”

This section defines the desired end-user experience for running FaceForge Core locally and the specific design decisions intended to reduce friction in that process as much as possible.

12.1 Network Ports

12.2 Desktop Launcher Experience (Cross-Platform)

A desktop launcher is a first-class deliverable.

Release UX requirements: - ship a FaceForge Desktop app (Tauri) that behaves like a real app: - first-run wizard for choosing FACEFORGE_HOME and Core port - starts/monitors required components (Core API service, SeaweedFS services, plugin runners) - exposes only the UI/API port - minimizes to system tray instead of exiting when the window is closed - tray menu: Open UI, Status, Logs, Stop, Restart, Exit - on exit: prompt whether to stop services or leave them running

User-facing simplification goals: - one installer per OS (or portable zip where appropriate) - one desktop launcher app - one user-chosen data directory - no loose scripts

Documentation is written for non-engineers first and includes screenshots of first-run and tray controls.

12.3 Runtime Constraints

12.4 Packaging Notes (Implementation Direction)

TO-DO: Update strategy for the Core service, SeaweedFS, and plugin bundles.

12.5 Dev Bundling (Standard Commands + Outputs)

This section standardizes how developers produce bundled artifacts locally for testing and validation.

Scope: “bundling” here means producing:

Prerequisites (Windows):

Note: All repo scripts are designed to run with the repo-local .venv and will create it automatically if missing.

12.5.0 macOS/Linux note (current state)

Bundle Core manually (macOS/Linux):

python3.12 -m venv .venv
./.venv/bin/python -m pip install --upgrade pip
./.venv/bin/python -m pip install -e ./core
./.venv/bin/python -m pip install pyinstaller

cd core
../.venv/bin/python -m PyInstaller pyinstaller.spec --noconfirm --distpath dist --workpath build

Expected outputs (macOS/Linux):

Build Desktop installers (macOS/Linux):

cd desktop/src-tauri
cargo tauri build

Expected outputs (macOS/Linux):

12.5.1 Bundle Core (PyInstaller)

From the repo root:

./scripts/check-core.ps1
./scripts/build-core.ps1

What it does:

Primary outputs:

Secondary outputs (implementation detail):

Common options:

12.5.2 Bundle Desktop (Windows MSI via Tauri)

This creates an installer that bundles the desktop shell plus the Core binary as a sidecar.

1) Build Core (produces core/dist/faceforge-core.exe):

./scripts/build-core.ps1

2) Stage the Core binary into Desktop’s Tauri bundle inputs:

New-Item -ItemType Directory -Force -Path 'desktop/src-tauri/binaries' | Out-Null
Copy-Item -Force 'core/dist/faceforge-core.exe' 'desktop/src-tauri/binaries/faceforge-core-x86_64-pc-windows-msvc.exe'

3) Build the Desktop installer:

Push-Location 'desktop/src-tauri'
cargo tauri build
Pop-Location

Primary outputs (Windows):

Note: The exact MSI filename includes the app name and version; treat *.msi under that folder as the output.

12.6 New Release (Standard Process + CI Sequence)

This section standardizes how new releases are cut and what happens inside GitHub Actions when release assets are produced.

12.6.1 Local maintainer steps (version bump → tag → release)

1) Ensure your working tree is clean and CI is green locally:

./scripts/check-core.ps1

2) Choose the new version number (SemVer: X.Y.Z).

3) Bump versions across Core + Desktop in one go:

./scripts/set-version.ps1 -Version X.Y.Z

This updates, at minimum:

4) Update human-facing release notes (as appropriate):

5) Commit the version bump + notes:

git add -A
git commit -m "chore(release): vX.Y.Z"

6) Create and push the tag (release automation expects a v-prefixed tag):

git tag vX.Y.Z
git push origin HEAD
git push origin vX.Y.Z

7) Create a GitHub Release for tag vX.Y.Z and publish it.

Alternative: you may run the release workflow manually via workflow_dispatch and provide tag: vX.Y.Z.

12.6.2 What GitHub Actions does (release-core workflow)

When a release is published (or the workflow is manually dispatched), GitHub Actions runs .github/workflows/release-core.yml.

Sequence (Windows release assets job):

1) Check out the repository at the release tag. 2) Ensure core/pyinstaller.spec exists (for legacy tags it may be fetched from the default branch). 3) Sync version metadata from the tag (best-effort safety net). 4) Set up Python 3.12. 5) Set up Rust toolchain. 6) Install Tauri CLI (cargo install tauri-cli --locked). 7) Install WiX toolset (MSI tooling). 8) Build the Core executable by running ./scripts/build-core.ps1. 9) Collect/normalize Core output into core/dist/faceforge-core.exe. 10) Stage Core into Desktop sidecar binaries: - desktop/src-tauri/binaries/faceforge-core-x86_64-pc-windows-msvc.exe 11) Build the Desktop MSI via cargo tauri build. 12) Collect release artifacts into artifacts/release/: - Desktop *.msi - faceforge-core.exe - SHA256SUMS.txt (SHA-256 hashes of the files above) 13) Upload these files to the GitHub Release as downloadable assets.

Published release assets (expected):