How FreeLLMAPI Syncs Its Model Catalog: Cryptographic Verification and Three-Phase Architecture
FreeLLMAPI synchronizes its local model catalog through a three-phase process involving boot-time cache restoration, periodic 12-hour polling against a signed remote endpoint, and Ed25519 cryptographic verification before atomic SQLite application.
According to the tashfeenahmed/freellmapi source code, the synchronization mechanism balances offline availability with cryptographic security. The system maintains a local cache of cryptographically signed catalogs while ensuring stale or tampered data cannot be applied through strict version gating and signature validation.
The Three-Phase Synchronization Architecture
FreeLLMAPI implements a robust synchronization pipeline defined in /server/src/services/catalog-sync.ts. The architecture separates concerns between initial startup, background maintenance, and data validation.
Phase 1: Boot-Time Cache Restoration
When the server starts, FreeLLMAPI immediately re-applies the previously fetched catalog stored in the SQLite settings table. This ensures the local model list remains operational even when the server starts without network connectivity.
The reapplyCachedCatalog() function (lines 19-33) reads the SETTING_APPLIED_JSON setting, validates its structural shape, and invokes applyCatalog() to restore the database state:
// Boot-time restoration ensures offline operation
import { reapplyCachedCatalog } from './services/catalog-sync';
await reapplyCachedCatalog(); // Reads SETTING_APPLIED_JSON from settings table
Phase 2: Periodic Remote Polling
A scheduler initiates background synchronization every 12 hours using an initial delayed run. The startCatalogSync() function (lines 42-55) registers a boot-delay timer and an interval using SYNC_INTERVAL_MS (set to 12 hours), triggering syncCatalog() on each iteration:
import { startCatalogSync } from './services/catalog-sync';
import { Scheduler } from './lib/scheduler';
const scheduler = new Scheduler();
startCatalogSync(scheduler); // Polls every 12h + runs once after 10s delay
If network failures or verification errors occur, the system logs warnings to SETTING_LAST_ERROR and retries automatically on the next scheduled interval without crashing the service.
Phase 3: Fetch, Verify, and Apply
The syncCatalog() function (lines 78-94) orchestrates the remote fetch and validation pipeline. It constructs a request to <BASE_URL>/v1/latest with optional query parameters for incremental updates, validates cryptographic signatures, checks version compatibility, and delegates database updates to applyCatalog().
Cryptographic Verification and Integrity Checks
FreeLLMAPI treats catalog authenticity as a security boundary, implementing multiple validation layers before database modification.
Ed25519 Signature Validation
Every catalog response includes an x-catalog-signature header containing a Base64-encoded Ed25519 signature. The system verifies response body bytes against either the CATALOG_PUBKEY environment variable or a hard-coded PINNED_CATALOG_PUBKEY (lines 66-73) using Node.js crypto.verify():
// Signature verification implementation (lines 103-108)
const signature = Buffer.from(response.headers['x-catalog-signature'], 'base64');
const valid = crypto.verify('ed25519', bodyBytes, publicKey, signature);
if (!valid) throw new Error('Catalog signature verification failed');
Failed verification immediately discards the catalog, preventing tampered model definitions from entering the local database.
Structural and Version Validation
Before application, the parsed JSON undergoes structural validation through the isCatalog() type guard (lines 91-150), ensuring required fields—including version, tier, models, and quirks—are present.
The system also enforces a MIN_CATALOG_VERSION constant (set to 2026.06.07 per lines 13-15) to prevent rollbacks that might remove models added by newer migrations:
if (catalog.version < MIN_CATALOG_VERSION) {
throw new Error(`Catalog version ${catalog.version} is below minimum ${MIN_CATALOG_VERSION}`);
}
Database Transaction Strategy
Once validated, catalog application occurs within a single SQLite transaction to maintain atomicity and data consistency.
Atomic Application with SQLite
The applyCatalog() function (lines 75-120) wraps all modifications in a database transaction, iterating over chat models, media models, video, embedding, and transcription entries. It handles:
- Insertion of new model rows
- Updates preserving user-added configurations and respecting the
enabledflag - Deletion of catalog-managed rows absent from the new catalog
- Quirk replacement via complete clearing and re-insertion of model quirks
Model Lifecycle Management
Helper functions including applyModelOverrides() and isCatalogModelTombstoned() manage model-specific overrides and tombstone handling during the apply phase. After successful transaction commit, the system persists metadata to the settings table:
// Persisting sync state
setSetting('SETTING_APPLIED_VERSION', catalog.version);
setSetting('SETTING_APPLIED_TIER', catalog.tier);
setSetting('SETTING_APPLIED_JSON', JSON.stringify(catalog));
setSetting('SETTING_LAST_SYNC_MS', Date.now());
Manual Synchronization and State Inspection
Administrators can force immediate synchronization bypassing the incremental since parameter, or inspect current sync state for diagnostics:
// Force manual sync (e.g., after adding premium license)
import { syncCatalog } from './services/catalog-sync';
await syncCatalog(true); // bypasses the `since` short-circuit
// Inspect current sync state
import { getSyncState } from './services/catalog-sync';
const state = getSyncState();
console.log('Catalog version:', state.appliedVersion);
console.log('Last sync (ms):', state.lastSyncMs);
Premium license keys (SETTING_LICENSE_KEY) are transmitted as Bearer tokens during fetch requests, enabling tier-specific catalog access while maintaining the same cryptographic verification flow.
Summary
- Boot-time resilience:
reapplyCachedCatalog()restores the last known good catalog fromSETTING_APPLIED_JSONduring server startup, ensuring offline operation. - Cryptographic trust: All catalogs require valid Ed25519 signatures verified against pinned or configured public keys before database application.
- Version safety: The
MIN_CATALOG_VERSIONgate prevents accidental rollbacks to outdated catalog schemas. - Atomic updates:
applyCatalog()executes within a single SQLite transaction, handling insertions, updates, deletions, and quirk management atomically. - Incremental efficiency: The
?sincequery parameter enables 304 Not Modified responses when the local catalog is current, reducing bandwidth.
Frequently Asked Questions
How frequently does FreeLLMAPI check for catalog updates?
The system polls the remote catalog endpoint every 12 hours via SYNC_INTERVAL_MS, with an initial delayed execution 10 seconds after server boot. This interval balances freshness against server load and can be triggered manually via syncCatalog(true) when immediate updates are required.
What prevents malicious catalogs from compromising the local database?
FreeLLMAPI implements defense in depth: all catalogs must carry a valid Ed25519 signature in the x-catalog-signature header verified against PINNED_CATALOG_PUBKEY or the CATALOG_PUBKEY environment variable. Additionally, structural validation via isCatalog() and version gating against MIN_CATALOG_VERSION ensure only properly formed, recent catalogs pass validation.
Can FreeLLMAPI operate without internet connectivity?
Yes. The boot-time cache restoration mechanism ensures that if SETTING_APPLIED_JSON exists in the local SQLite database, the server can start and serve models using the previously synchronized catalog. The background scheduler will continue attempting updates every 12 hours, but operation proceeds using cached data during outages.
How are user-configured model settings preserved during updates?
During applyCatalog(), the system preserves user-added rows and respects the enabled flag when updating existing models. The transaction strategy ensures that user customizations survive catalog refreshes while still removing genuinely deleted models and applying new quirks from the authoritative source.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →