SDK catalog / Profit Ledger

Profit Ledger

alpha 0.1.0-alpha.5

Published release candidate for @wf/profit-ledger@0.1.0-alpha.5. Follow the registry guide and review compatibility before installing.

Join the alpha Sign in with Google, then add your name. We review alpha access requests.

Transaction-level gross profit for GHL, without CSV exports. Published by BrightOps. Alpha release through the BrightOps licensed registry; request access from the catalog.

Use

Install the packaged preview with npm, copy examples/profit-ledger.yaml, and list the authorized GHL location IDs. The package includes its Core and GHL dependencies. Buyers need Node.js 22 or newer, their own GHL token with payments/transactions.readonly, and cost allocations for each transaction. No Workforce checkout is needed.

For a complete credential-free buyer example, run node node_modules/@wf/profit-ledger/examples/buyer.mjs /absolute/path/profit-ledger.yaml <allowed-location-id>. It calculates supplied example data through the installed client: $80 collected after a $20 refund, $60 cost, $20 gross profit, 25% margin, and $17 after fees. Live sync uses the same client with the host callbacks below.

import { createProfitLedger } from '@wf/profit-ledger'
const client = createProfitLedger('/app/profit-ledger.yaml', {
  resolveSecret: reference => secretStore.get(reference),
  authorize: (operation, locationId) => currentUser.canRead(locationId),
})
try {
  const ledger = await client.sync({ locationId, costs: [{ transactionId, costMinor: 6000 }] })
} finally { await client.close() }

All settings are loaded from YAML. Unknown fields, JSON configuration, invalid limits and configuration fields in runtime inputs are rejected. Runtime inputs are host authorization, secret resolution and an optional fetch transport. sync owns GHL requests, pagination, deduplication, bounded retries, cancellation and validation. calculate uses the same authorization and calculation engine on supplied transaction snapshots. No operation writes to GHL. close aborts and awaits active operations; create a new client to reopen.

Profit definition

All amounts are integer ISO-currency minor units. Net collected revenue is the payment less refunds. Gross profit is net collected revenue less the cost allocated to that payment; gross margin divides that profit by net collected revenue. Missing cost produces null gross profit and margin, profitStatus: provisional, and displayGrossProfitMinor: 0. Hosts must label that zero as provisional; it is neither a known zero profit nor a zero cost. Totals count missing costs and include only known profit. Currency totals are separate. Profit after processing fees remains unknown until a fee is supplied. These figures include tax or shipping in the payment and are not accounting net income.

Invoice payments include descriptive lineItems when the key also has invoices.readonly. Ad-hoc items need no product ID or cost to appear. One collected payment stays one ledger row regardless of item count. Missing invoice access leaves the payment visible with invoiceItemsStatus: unavailable; a foreign-location invoice fails closed. The adapter uses HighLevel v3 paymentMode, startAt, and endAt filters. Hosts persist cost snapshots and call calculate again to apply historical corrections without GHL writes or another sync.

Allocate an order's cost across its payments once; do not enter the full order cost against each installment. Refunds do not automatically return inventory or reverse cost. The host owns durable cost snapshots, returns policy and changes to allocations. Unknown/failed/pending payment statuses are excluded and counted. Duplicate direct inputs, foreign-location transactions, invalid money, stalled pagination and over-limit syncs fail without returning a misleading partial ledger.

WF and other hosts

Load the public @wf/profit-ledger/cordis plugin with configurationFile. Its profitLedger service exposes the same client as the buyer API. Supply a profitLedgerHost service for host authorization, credentials and transport. Unloading aborts pending reads. No invariant companion is needed: the plugin owns one client and no mirrored state. The JSON stdin bridge wf-profit-ledger --config <yaml> lets a Python host call this same engine after authenticating the request; it is one invocation, not a background daemon. The trusted-host bridge accepts operation, request, authorizedLocation, and an optional ephemeral credential on stdin; never log its input.

MCP

Current protocol: 2026-07-28; older protocols are rejected. wf-profit-ledger-mcp --config examples/mcp.yaml uses current-only MCP from Core. The standalone executable can calculate supplied data; a host calling createMcpServer supplies its own secret resolver for GHL sync. No environment-variable credential fallback exists.

Known Limitations and Deferred Work

Native GHL product cost and processing-fee availability are not assumed. The host supplies explicit transaction cost/fee snapshots. Product defaults never automatically rewrite payment allocations. GHL authorization and refresh belong to the host. Product access requires the customer’s approved scopes; an alpha installation can use supplied-data calculations before connecting. This release does not include Marketplace billing or an accounting compliance claim.

Alpha 5: reusable GHL and cost imports

Live reads now use @wf/ghl through its public API. Add ghlConfigurationFile: ghl.yaml to ledger YAML; paths resolve relative to that file. Copy the GHL YAML example beside it. The GHL client owns transport policy; configure its timeout/retries there. Calculation-only clients need no GHL configuration or credentials. Multiple-business hosts use authorization: host and provide an authorize callback; never accept a URL location as identity. Single-business buyers can keep allowedLocations.

parseCostCsv(csv) parses finished unit costs with exact productId, priceId, currency and unitCost columns. Optional productName and priceName are labels only. It rejects duplicate matches, invalid money, unknown columns, malformed quotes, files over 256 KiB and more than 1,000 rows. Hosts must verify each price belongs to the authenticated business, preview the parsed rows, and persist atomically. A material cost sheet is not a finished-unit cost import.

calculateItemCosts([{quantity,unitCostMinor}]) computes rounded line totals using exact decimal quantities (up to six decimal places) and integer currency minor units. A missing cost returns null. It does not allocate costs across partial payments. Hosts own that explicit allocation and append-only history; changing defaults must not rewrite past payments.

BrightOps’ alpha app supports 50-row verified imports per batch, product counts, local cost defaults and revision-checked payment edits. Its separate selling-price editor uses GHL. Native GHL Cost Price writes are not supported by the documented API and are not advertised as synced. Request alpha access at https://catalogue.brightops.io/#products. Support: sundar@brightops.io.