# How FreeLLMAPI Syncs Its Model Catalog: Cryptographic Verification and Three-Phase Architecture

> Discover how FreeLLMAPI syncs its model catalog using cryptographic verification and a robust three-phase architecture for reliable updates. Learn more.

- Repository: [Tashfeen/freellmapi](https://github.com/tashfeenahmed/freellmapi)
- Tags: architecture
- Published: 2026-09-04

---

**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`](https://github.com/tashfeenahmed/freellmapi/blob/main//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:

```typescript
// 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:

```typescript
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()`:

```typescript
// 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:

```typescript
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 `enabled` flag
- **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:

```typescript
// 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:

```typescript
// 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 from `SETTING_APPLIED_JSON` during 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_VERSION` gate 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 `?since` query 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.