Skip to main content

Flavor Core — Developer Overview

Flavor Core (flavor-core/) is the ecosystem's third first-party product: the License & Product Manager. It is the single entry point for license activation, product installation, and centralized updates across the whole ecosystem — the theme, the WP eCommerce Core plugin, and Core's own self-update. It also owns the unified Debug logger that all three products write to, and the AI/abilities foundation behind Flavor AI.

This page is an orientation map: what Core is, its main subsystems, its data domain, and the flavor_core_* helpers you can call from theme or plugin code. It links out to the deep-dive pages rather than repeating them.

First-party scope

The classes, files, and helpers named here are an internal / first-party developer surface — accurate for building on Flavor itself. They are documented as "how our systems work," not a frozen third-party contract. Pin integrations to a store version and re-check after upgrades.


Role in the ecosystem

Once Flavor Core is active it takes ownership of updates for the whole stack. The entry file defines FLAVOR_CORE_MANAGES_UPDATES = true, which signals the theme and plugin to stand down their own update hooks and let Core drive. Core boots early — on plugins_loaded at priority 5, ahead of theme/plugin licensing — so its license state and helpers are available before the products that depend on them initialize.

  • Entry file: flavor-core/flavor-core.php — plugin header, constants (FLAVOR_CORE_VERSION, FLAVOR_CORE_API_URL, FLAVOR_CORE_DIR, …), the global helpers, and the plugins_loaded bootstrap.
  • Hub endpoint: FLAVOR_CORE_API_URL (default https://license.flavorteam.dev), overridable in wp-config.php via the FLAVOR_HUB_API_URL constant for dev/staging.
  • Scheduled work: a twice-daily cron event (flavor_core_verify_cronflavor_core_cron_handler()) re-verifies licenses and checks for updates.

Crash-safe bootstrap

The very top of flavor-core.phpbefore any require_once — defines a zero-dependency emergency micro-logger (flavor_emergency_log()) that writes to wp-content/flavor-emergency.log. It uses only PHP core functions, so it survives a total class-load failure (for example, a self-update that leaves includes/ half-populated). Each require_once is wrapped so a missing or broken include is recorded there before PHP fatals. This file is separate from the normal wp-content/flavor-logs/ directory (which needs the logger class loaded) and is for crash-time forensics only — normal logging goes through flavor_core_log().


Key subsystems

Every subsystem is a class under flavor-core/includes/:

SubsystemClassResponsibility
License clientFlavor_Core_License_ClientTalks to the Hub API; caches per-product license state
Update managerFlavor_Core_Update_ManagerCentralized, atomic product + self-update
Admin UIFlavor_Core_Admin_PageThe Flavor admin screen (3-state) + the Flavor AI page
Unified loggerFlavor_Core_LoggerStructured JSON-Lines logging for all three products
Debug REST APIFlavor_Core_Debug_ApiThe flavor-core/v1 debug endpoints behind the Debug Viewer
Sensitive storeFlavor_Core_Data_StoreEncrypted {prefix}flavor_core_data (licenses, fingerprints)
Options storeFlavor_Core_Options_RepositoryNon-sensitive {prefix}flavor_core_options settings
AI foundationFlavor_Core_AI_FoundationBoots the abilities + MCP layer behind Flavor AI

License client

Flavor_Core_License_Client (includes/class-license-client.php) is the client for the Flavor Hub licensing API. It activates and verifies per-product licenses, caches the result in the encrypted data store, and exposes it to the rest of the ecosystem through the global helpers below. Its per-product resolution — status, staleness window, expiry, and fingerprint — is the same logic the theme and plugin license gates rely on, so a single hardened check backs every gate in the system.

Update manager

Flavor_Core_Update_Manager (includes/class-update-manager.php) drives every product update (theme, plugin) and Core's own self-update. Two design rules are worth knowing when you touch this path:

  • Updates are atomic. The manager extracts to a staging directory, verifies a full essential-file manifest, then does an atomic rename swap (live → .old, staging → live) with a rollback ladder. The live directory is never deleted before the replacement is confirmed. Never introduce a delete-then-extract-in-place step here.
  • Backup/restore lives in Core, not in the product being updated. During a self-update the old theme/plugin code is already loaded in PHP memory, so the backup and restore logic must run from Core (which is not the code being swapped). Do not delegate update-time backup to a theme/plugin installer.

Admin UI

Flavor_Core_Admin_Page (includes/class-admin-page.php) registers the top-level Flavor menu and renders a single page with three states selected from current license status:

  • Licensed — at least one product active → dashboard view.
  • Expired — a product license has expired → renewal view.
  • Fresh — no active license yet → activation / getting-started view.

It also registers the Flavor → Flavor AI submenu (the AI Center — outbound AI Content plus inbound AI Access), which is disabled until a Flavor license is active.

Unified debug logger

Flavor_Core_Logger (includes/class-logger.php) is the single logger shared by the theme, the plugin, and Core. It writes structured JSON Lines to wp-content/flavor-logs/, exposed through the Flavor_Core_Debug_Api (includes/class-debug-api.php) REST controller and the Debug Viewer SPA. Logging is clean-gated by the FLAVOR_DEBUG constant — when it is off, nothing is written and the log directory is never created.

For the full logging contract — helper signatures, PSR-3 levels, hierarchical channels, the FLAVOR_DEBUG gate, and the debug REST API — see Debugging & Logging.

AI / abilities foundation

Flavor_Core_AI_Foundation (includes/ai/class-flavor-ai-foundation.php) is the orchestrator behind Flavor AI. It boots on plugins_loaded but self-gates: the abilities loader, the MCP server, and the ability base class only load when the flavor-ai Core Component is installed. Custom abilities extend Flavor_Core_AI_Abstract_Ability (includes/ai/class-abstract-ability.php).

Do not document the AI layer from here — it has its own pages:


Data sovereignty — Core's own domain

Flavor Core is the third data domain (alongside the plugin's wpec_* and the theme's flavor_*). It owns all of its data in two custom tables — never in wp_options:

  • {prefix}flavor_core_datasensitive data (license cache, fingerprint token), AES-256-GCM encrypted at rest, accessed through Flavor_Core_Data_Store.
  • {prefix}flavor_core_optionsnon-sensitive settings (mode, release channel, MCP toggle, grace opt-in, self-update diagnostics, migration markers), accessed through Flavor_Core_Options_Repository and the flavor_core_*_option() helpers below.

The only permitted wp_options residue is the per-store bootstrap markers (the schema/migration flags that must exist before the Core tables do). Everything else uses the helpers.

// Read / write / delete Flavor Core settings — non-sensitive options table
flavor_core_get_option('release_channel', 'stable');
flavor_core_set_option('mcp_enabled', 'true', /* autoload */ false, 'general');
flavor_core_delete_option('some_stale_flag');

// NEVER do this:
update_option('flavor_core_release_channel', 'stable'); // WRONG!
get_option('flavor_core_mcp_enabled'); // WRONG!

See Data Sovereignty for the full three-domain rules, tables, and the encrypted store.


Developer helpers

Flavor Core exposes global helper functions you can call from theme or plugin code once Core is active. The signatures below are the current, code-confirmed ones.

Options

flavor_core_get_option(string $key, $default = null);
flavor_core_set_option(string $key, $value, bool $autoload = false, string $group = 'general'): bool;
flavor_core_delete_option(string $key): bool;

These mirror the theme/plugin option API and route to Flavor_Core_Options_Repository. During the one-time storage migration (or before the repository class is loaded in very early boot) they fall back to wp_options so nothing breaks in the upgrade window.

License status

flavor_core_is_licensed(string $product = ''): bool;

Returns whether a product is licensed through Flavor Core. Pass 'plugin' or 'theme' for a specific product, or an empty string to check whether any licensed product is active. This is the hardened check — it verifies license status, the staleness window, expiry (honoring an opted-in grace window), and fingerprint validity — the same boundaries the per-product license gates use. Use it to gate premium features instead of reading the license row directly.

Logging — mind the argument order

Core's log helper is flavor_core_log(). Its argument order differs from the theme and plugin helpers — a genuine footgun:

// Flavor Core — LEVEL first, then message:
flavor_core_log(string $level, string $message, array $context = [], string $source = 'core', string $channel = '');
flavor_core_log('error', 'Update failed', ['product' => 'theme'], 'core', 'core.updates');

// Theme / plugin — MESSAGE first, then level:
flavor_log('Cart rebuilt', 'info', 'theme.module.cart');
wpec_log('Gateway timeout', 'error', 'plugin.gateway.stripe');
Argument order

flavor_core_log() takes (level, message, …) while flavor_log() / wpec_log() take (message, level, …). Passing a message where a level is expected produces a misfiled entry, not an error — copy the signature, don't guess. See Debugging & Logging for the full logging contract.

A zero-dependency flavor_emergency_log() also exists for crash-time forensics (writes to wp-content/flavor-emergency.log); use the normal flavor_core_log() for everything else.

Debug REST namespace

Core registers its own REST namespace, flavor-core/v1, for the debug subsystem (log entries, stats, settings, export, diagnostics). It is distinct from the plugin's ec/v1 and the theme's flavor/v1. Access is restricted to manage_options; the Debug Viewer SPA is its primary consumer.


Where to go next