Documentation
¶
Overview ¶
activeplan.go answers the subscription paywall's ONE question: does org X hold a LIVE PAID plan? It is the commerce "active-subscription check" — the tier sibling of CheckEntitlement (per-product license). CheckEntitlement deliberately cannot answer this: it filters Status=Active ONLY (a TRIALING subscriber would be mis-read as unentitled) and it is scoped to a single product id, whereas the paywall gates on the PLAN TIER regardless of product. So ActivePaidPlan is a distinct read over the SAME org resolver + subscription store, counting ACTIVE *and* TRIALING subscriptions and classifying the tier through @hanzo/plans (clients/plan.Paid) — the single source of truth for which tiers cost money.
It is an OPTIONAL capability on the in-process client (not on the narrow types.CommerceClient interface): the paywall (routers.PlanChecker) resolves it by type-assertion, mirroring types.ModelLister. A commerce build that cannot answer (split-deploy ZAP client, disabled stub) simply does not implement it, and the paywall fails OPEN — an outage never locks out a subscriber.
client.go is the in-process inter-subsystem commerce client — the REAL implementation of cloud's types.CommerceClient, absorbed here from the retired in-process stub that used to fail closed on entitlement. It answers cloud's licensing/entitlements tier with DIRECT Go calls into the embedded commerce datastore (subscriptions) plus the @hanzo/plans vocabulary (plan → license features) — no HTTP hop, no network.
MONEY-SAFETY. CheckEntitlement NEVER fabricates a grant. It returns Active:true ONLY when a real active, unexpired subscription in the org's own datastore namespace holds a plan tier whose @hanzo/plans license-features actually name the product. Any machinery it cannot resolve (commerce not co-resident, org not resolvable, subscription query error, plans vocabulary unavailable) returns an ERROR — the entitlements gate treats an erroring client as "cannot verify ⇒ 503", the specified secure default, so an unverifiable product is never enabled. A clean "resolved, but no plan licenses this product" is a real Active:false answer (the gate turns it into a 402 upgrade prompt), never an error and never a grant.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func BalanceCents ¶
BalanceCents returns subject's available prepaid balance (USD cents) in org, read DIRECTLY from the co-resident embedded commerce ledger — no HTTP hop. It is the native twin of the /v1/billing/balance read (billing.zapGetBalance): resolve the org's own datastore namespace, tally the subject's iam-user transactions in the currency, and return Balance - Holds clamped at zero. It reuses the SAME currentEmbedded seam the in-process entitlement client resolves through.
This is the read the money cutover (admin/finance backfill) and the admin cockpit's credit panels use when commerce runs in the SAME binary: the admin commerce HTTP client dials an unroutable in-proc address and reads $0, which would silently migrate/report nothing. When commerce is NOT co-resident this returns an ERROR (never 0), so a caller can tell "not wired" from a real zero balance and fail loud rather than move money on a phantom figure. Subject is lowercased + trimmed; an empty currency defaults to usd.
func PublishEmbedded ¶
func PublishEmbedded(e *commercemod.Embedded)
PublishEmbedded records the mounted Embedded as the in-process entitlement source. Mount calls it once; nil un-publishes (tests).
Types ¶
type Client ¶
type Client = types.CommerceClient
Client is the in-process inter-subsystem seam cloud's licensing/entitlements tier calls. It IS cloud's types.CommerceClient — one narrow interface (GetOrgConfig + the real CheckEntitlement), not a second copy — kept as an alias so a value satisfies both names with no adapter. Add methods here only when a consumer needs them; keep it narrow.
func InProcessClient ¶
InProcessClient returns the process-wide, lazily-resolved client cloud's pickCommerceClient wires as deps.Commerce. BuildDeps runs before MountAll, so it resolves the published Embedded per call rather than capturing one; brand answers OrgConfig even before Mount publishes.