SIGN IN SIGN UP

feat(checkpoints): Evaluate checkpoint custom variables as custom.* dimensions (#3949)

### Description

Makes a checkpoint's custom variables readable from a rule predicate as
`custom.<key>`, so the same checkpoint can behave differently depending
on how it was reached.

Similar to iOS (RevenueCat/purchases-ios#7393)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes which checkpoint workflow wins when rules use `custom.*`
predicates, and renames an internal API (`customProperties` →
`customVariables`) that callers must adopt.
> 
> **Overview**
> Renames checkpoint **`customProperties`** to **`customVariables`** on
`CheckpointParams`, `Purchases.resolveCheckpoint`, and the resolver
stack so naming matches paywalls and iOS.
> 
> Checkpoint resolution now feeds those per-call values into **local
rule evaluation** as **`custom.<key>`** dimensions (alongside
`device.*`). Invalid keys and unsupported value types are dropped with
warnings instead of failing the whole evaluation. Shared
**`CustomVariableKeyValidator`** lives in the purchases module and
replaces the UI-only copy; paywall and checkpoint paths both use it.
> 
> **`LocalRulesEvaluator.match`** and
**`RulesDimensionResolver.snapshot`** accept optional custom variables;
an empty map leaves the `custom` namespace absent (not an empty object).
**`CheckpointWorkflowResolverImpl`** passes converted variables when
matching checkpoint audience rules.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
2c5c00a46e9ac424b42fb83825922ce0f6b7d9af. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
T
Toni Rico committed
1473a35e463e149bebf2947c6488429dd51e4566
Parent: 5c5979e
Committed by GitHub <noreply@github.com> on 8/14/2026, 9:32:00 AM