WP Manifestindependent plugin directory
manifest / ecommerce / blt-fluent

BLT Fluent WP Registry grade A-. Low-severity findings · 1 findingWP RegistryLow-severity findings · 1 findingOpen the reportA-

A series of extensions for FluentCart & FluentCRM

★ 1stars
4release downloads
v0.2.0latest · 1mo ago

Install

Download blt-fluent-0.2.0.zip From the v0.2.0 release on GitHub, Aug 27, 2026

Upload it under Plugins → Add New Plugin → Upload Plugin, then activate.

Install straight from GitHub with WP-CLI:

wp plugin install https://github.com/s-fx-com/blt-fluent/releases/download/v0.2.0/blt-fluent-0.2.0.zip
Updates itself. It ships its own updater (Plugin Update Checker), so new versions appear under Dashboard → Updates.

A series of extensions for FluentCart & FluentCRM.

BLT Fluent lets an administrator pick which FluentCRM custom contact fields are collected during FluentCart checkout, order them by drag-and-drop, and enable that field set per product. Submitted values are written straight to the customer's FluentCRM contact record.

FluentCRM owns the schema; this plugin stores configuration only. No ACF bridge, no user-meta duplication, no Fluent Forms dependency.

Requirements

Requirement Minimum
WordPress 6.5 (for the Requires Plugins header)
PHP 7.4
FluentCart 1.4.0
FluentCRM 2.8.0

Dependencies are enforced in three layers: the Requires Plugins header, an activation guard that blocks direct/WP-CLI activation, and a runtime guard that shows a notice and registers nothing — but never self-deactivates, so configuration is never silently destroyed.

Install for development

git clone git@github.com:s-fx-com/blt-fluent.git wp-content/plugins/blt-fluent
cd wp-content/plugins/blt-fluent
bin/install-puc.sh          # fetches Plugin Update Checker into vendor/

Plugin Update Checker is not committed. The plugin works without it — only the self-update mechanism is inert, and the Diagnostics panel says so.

For the private-repo updater, add a fine-grained read-only PAT to wp-config.php:

define( 'BLT_FLUENT_GH_TOKEN', 'github_pat_...' );

Release

  1. Bump Version: in blt-fluent.php and Stable tag: in readme.txt.
  2. bin/build-zip.sh
  3. Tag vX.Y.Z and attach build/blt-fluent-X.Y.Z.zip as a release asset.

The site checks for updates once a day at local midnight: PUC's own scheduler is disabled ($checkPeriod = 0) and a WP-Cron event anchored to wp_timezone() drives checkForUpdates() instead. Note that WP-Cron is lazy — on a low-traffic site the event fires on the first page load after midnight. The Plugins screen "Check for updates" link and the Diagnostics tab button both still work for manual checks.

Data lifecycle

Event Config in wp_options Cron event FluentCRM data
Activate Preserved if present; defaults seeded only if absent Scheduled if not already Untouched
Deactivate Preserved Unscheduled Untouched
Reactivate Preserved Rescheduled Untouched
Plugin update Preserved; migrated by version key Preserved Untouched
Uninstall (delete) Deleted only if delete_on_uninstall is true Unscheduled Always untouched

The uninstall opt-in covers this plugin's configuration only. FluentCRM contacts, field definitions and values, FluentCart orders and products, and anything written by the profile-edit form are never deleted.

Company selection

[blt_fluent_company] renders a company picker for the signed-in member. Typing searches FluentCRM's existing companies; picking one and pressing Save writes it to that member's contact record. A name matching nothing offers + Add a new company, so members land on an existing record wherever one exists and only create a company deliberately.

Attribute Default Purpose
label Company Field label
placeholder Start typing your company name… Input placeholder
button Save Save button text
help (none) Help text under the field
allow_create yes Whether the "add a new company" option appears
min_chars 2 Characters before searching

allow_create controls the interface only. The enforcement point is the blt_fluent/company_allow_create filter, because an attribute cannot be trusted to survive the round trip to the REST endpoint:

add_filter( 'blt_fluent/company_allow_create', '__return_false' );

Whose record gets written. The contact is resolved server-side from the signed-in user's email. No contact identifier is accepted from the request, so a member can only ever change their own company. Both endpoints require a signed-in user, and REST cookie authentication additionally requires the wp_rest nonce the script sends.

Duplicate companies. A submitted name is matched case-insensitively against existing companies before anything is created, so "acme ltd" attaches to the existing "Acme Ltd". Creation is also rate limited per member (5 an hour by default, blt_fluent/company_create_limit).

REST endpoints, namespace blt-fluent/v1:

Route Method Purpose
/companies?q= GET Search companies by name
/company POST Set the member's company (company_id or company_name)

FluentCart hooks used

Stage Hook Type
Render fluent_cart/before_payment_methods (filterable) action
Validate fluent_cart/checkout/validate_data filter
Persist fluent_cart/checkout/prepare_other_data action

fluent_cart/checkout/customer_data_saved was removed in FluentCart 1.4.0 and is deliberately not used — a callback on it never runs, silently.

The render hook defaults to fluent_cart/before_payment_methods because it fires in the standard, modal and block renderers. fluent_cart/checkout/b2b_extra_fields fires in the full-page renderer only.

Filters

Every assumption about FluentCart's payload shapes is overridable without a code change:

Filter Purpose
blt_fluent/render_hook Swap the action the fields render on
blt_fluent/cart_pairs Override the detected product/variation pairs
blt_fluent/cart_sources Add a FluentCart cart accessor to try
blt_fluent/field_set_key Choose the field set for the current cart outright
blt_fluent/is_renewal Override the renewal decision
blt_fluent/prepared_fields Add, remove or reshape fields before render
blt_fluent/multi_value Change how multi-value fields are serialised
blt_fluent/error_key Change the key validation errors are reported under
blt_fluent/contact_email Supply the contact email when detection fails
blt_fluent/crm_contact_payload Adjust the FluentCRM createOrUpdate payload
blt_fluent/order_meta_payload Adjust or skip the order-meta audit trail
blt_fluent/crm_field_definitions Adjust the FluentCRM field definitions
blt_fluent/capability Capability required to manage the plugin
blt_fluent/company_shortcode_tag Rename the shortcode
blt_fluent/company_allow_create Whether members may create companies
blt_fluent/company_create_limit Companies one member may create per hour
blt_fluent/company_contact_email Email used to find the member's contact
blt_fluent/pre_company_search, blt_fluent/company_search_results Override company search
blt_fluent/pre_create_company, blt_fluent/new_company_data Override company creation
blt_fluent/pre_assign_company Override attaching a company to a contact
blt_fluent/company_logged_out_message, blt_fluent/company_no_contact_message Front-end messages
blt_fluent/github_url, blt_fluent/github_branch, blt_fluent/github_token Updater source

Actions: blt_fluent/booted, blt_fluent/after_render, blt_fluent/values_written, blt_fluent/captured, blt_fluent/company_created, blt_fluent/company_saved.

Tests

php tests/smoke-test.php
php tests/company-test.php

tests/bootstrap.php is a small WordPress shim — enough of the API for the sanitisation, normalisation, validation and render code to run from the CLI. The FluentCRM readers are swapped for stubs, so the tests never need FluentCart or FluentCRM installed. CI runs both files plus php -l on 7.4, 8.2 and 8.4.

Build status

Phase Deliverable State
0 Skeleton, dependency guards, PUC + cron Built
1 Checkout capture end-to-end Built — needs live verification
2 Validation Built
3 Config layer (picker, ordering, product map) Built
4 Pre-fill + renewal skip Built
5 Hardening (multi-value, orphans, modal, i18n) Built — items 1, 4, 5 in docs/VERIFY.md need a live install
— Company selection shortcode Built — items 9-11 in docs/VERIFY.md need a live install

docs/VERIFY.md lists the assumptions that can only be settled against equinephotographers.org, each with the filter that fixes it if the assumption turns out wrong. Turn on Advanced → Record a diagnostic log before starting: the log names the cart-detection strategy, the FluentCRM read path, and every skipped or aborted write.

Releases

2 releases. Each count is every asset in that release; expand a row for the breakdown.

Tag
Published
Assets
Downloads
v0.2.0 latest
Aug 27, 2026 1mo ago
blt-fluent-0.2.0.zip
3
Aug 26, 2026 1mo ago
blt-fluent-0.1.1.zip
1
A- grade

Security

BLT Fluent 0.2.0 · audited by WP Registry

Low-severity findings only.

1 low
Audited release
0.2.0
Findings
1
Worst severity
low
Content hash
c8c45b4ef06684f6fe8dce94…

Findings

  • low Subscriber can enumerate CRM companies and self-assign any company

    information_disclosure

    The company REST routes only require is_user_logged_in(). GET /companies returns up to the search limit of FluentCRM company records (id, name and a meta line built from industry, city, country, website) for any search term, letting any registered user enumerate the CRM company directory. POST /company assigns the caller's contact to any existing company_id without verifying the user is affiliated with it, which may pollute CRM segmentation or any automation keyed on company membership.

    includes/class-company-shortcode.php:337-386, 414-487

    Recommendation

    Restrict search to a minimum term length and limited fields, and consider restricting assignment to companies matching the user's email domain or requiring admin approval.

WP Registry hashes the installable build and reports on that exact bytes-for-bytes copy. Embargoed findings are withheld until they are disclosed, so a clean verdict means nothing public is outstanding. WP Manifest does not audit code itself.