feat(license): add Lite SKU; remove user-facing free trial
Two coupled changes:
1. Lite tier
- New Tier.LITE in src/license/schema.py.
- FEATURES_BY_TIER[Tier.LITE] = {Deduplicator, Text Cleaner,
Format Standardizer}. The three universally-useful tools that
cover the most common bookkeeping / RevOps / Klaviyo prep
workflows. Other six tools require Core.
- i18n: license.tier_lite, license.feature_locked_title,
license.feature_locked_body, license.upgrade_link,
license.status_locked (en + es).
- Per-tool feature gate at every GUI tool page
(require_feature_or_render_upgrade) and every tool CLI
(guard(feature=...)). A locked tool renders an upgrade
prompt + Manage-license button (GUI) or exits with code 2
(CLI).
- Home grid: tool cards the user's tier doesn't unlock get a
red 🔒 Locked badge in place of green Ready.
2. Trial removed
- Activation form's "Start 1-year trial" button removed.
- license_cli's `trial` subcommand removed.
- activation.trial_button / activation.trial_help i18n keys
dropped (pack parity test stays green).
- Tier.TRIAL stays in the enum (back-compat with any field-
tested trial licenses); LicenseManager._mint stays internal
for tests and the seller's key generator.
- Decision logged in DECISIONS §9b: a 1-year all-features
trial undercuts paid Lite; paid-only keeps tier economics
clean.
Tests (+29 net): +17 Lite-tier unit/guard tests + 13 Lite-tier
GUI tests + 1 trial-absent assertion - 2 trial CLI tests - 1
trial GUI button test. Total: 1995 → 2024.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -174,13 +174,14 @@ and proceeds.
|
||||
- **Dev**: pytest, tox.
|
||||
|
||||
## 16. Test coverage
|
||||
- 1,995 tests passing, 0 skipped, 0 xfailed.
|
||||
- 1,843 core + CLI tests (run with `pytest -m 'not gui'` for a quick loop).
|
||||
Includes 40 license-layer unit tests + 26 license-CLI tests.
|
||||
- 152 GUI tests under `tests/gui/` driving Streamlit pages via `AppTest`
|
||||
- 2,024 tests passing, 0 skipped, 0 xfailed.
|
||||
- 1,859 core + CLI tests (run with `pytest -m 'not gui'` for a quick loop).
|
||||
Includes 40 license-layer unit tests, 25 license-CLI tests, and
|
||||
17 Lite-tier feature-map + guard tests.
|
||||
- 165 GUI tests under `tests/gui/` driving Streamlit pages via `AppTest`
|
||||
(smoke + EN/ES localization, chrome, gate, workflows, dedup review,
|
||||
advanced panels, error paths, findings panel, activation + license
|
||||
gate). Marked `gui`.
|
||||
advanced panels, error paths, findings panel, activation +
|
||||
license gate, Lite-tier per-page lock behaviour). Marked `gui`.
|
||||
- Includes 15 perf-shape regression tests.
|
||||
- Fixture corpora: text-cleaner (21), encodings (31), reference UTF-8 (9), format-cleaner (199 buyer cases + 20-row international stress fixture), missing-handler (3 use cases + 16 edge cases), column-mapper (3 use cases + 5 edge cases).
|
||||
- Run: `python run_tests.py [--tool …] [--fixtures] [--coverage]`.
|
||||
@@ -199,15 +200,31 @@ and proceeds.
|
||||
(``DTLIC1:...``) on first launch; app verifies the signature
|
||||
offline + matches the buyer-entered name/email to the embedded
|
||||
values.
|
||||
- **No free trial**: every license requires a paid blob from the
|
||||
seller. The user-facing trial flow (button + ``license_cli trial``
|
||||
subcommand) was removed in v1.6 to keep paid-tier economics clean.
|
||||
- **Lifetime**: every license is 1 year by default. Renewal applies a
|
||||
fresh blob without losing the embedded buyer identity.
|
||||
- **Tiers**: ``trial``, ``core`` (the v1 SKU — all 9 tools), ``pro``,
|
||||
``enterprise``. PRO and ENTERPRISE are scaffolded for future SKUs;
|
||||
they currently unlock the same feature set as CORE.
|
||||
fresh blob without losing the embedded buyer identity. Tier may
|
||||
change during renewal (Lite → Core upgrade path).
|
||||
- **Tiers**:
|
||||
- ``lite`` — Deduplicator + Text Cleaner + Format Standardizer.
|
||||
Buyer pays once, gets the three universally-useful tools.
|
||||
- ``core`` — every Ready tool (all 9 in v1.6).
|
||||
- ``pro``, ``enterprise`` — scaffolded for future SKUs; currently
|
||||
mirror Core. Add per-SKU restrictions by editing
|
||||
``FEATURES_BY_TIER`` in ``src/license/features.py``.
|
||||
- ``trial`` — kept in the enum for backwards compat with any
|
||||
field-tested trial licenses but no longer issuable.
|
||||
- **Feature flags**: every tool has a stable feature id matching its
|
||||
``tool_id`` in :mod:`src.gui.tools_registry`. Adding a future per-
|
||||
tool SKU is a one-line change to ``FEATURES_BY_TIER`` — no consumer
|
||||
code edits.
|
||||
- **Per-tool gating**: each tool page (GUI) and tool CLI calls
|
||||
``require_feature(FeatureFlag.<TOOL>)`` at entry. GUI shows an
|
||||
upgrade prompt + button to the Activate page; CLI prints a
|
||||
message naming the locked feature and exits with code 2.
|
||||
- **Lock badge**: the home grid shows a red 🔒 Locked pill on tool
|
||||
cards the current tier doesn't unlock.
|
||||
- **Dev bypass**: ``DATATOOLS_DEV_MODE=1`` skips every check (used by
|
||||
the test suite and during development).
|
||||
- **No internet**: signature verification is fully offline. The
|
||||
|
||||
Reference in New Issue
Block a user