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_cron → flavor_core_cron_handler()) re-verifies licenses and checks for updates.

Crash-safe bootstrap​

The very top of flavor-core.php — before 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_data — sensitive data (license cache, fingerprint token), AES-256-GCM encrypted at rest, accessed through Flavor_Core_Data_Store.
  • {prefix}flavor_core_options — non-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​