Legacy subscription tier contract
The customer plans, login states, feature boundaries, and enforcement gaps carried from the legacy Pages Router app into the Expo and experimental web catalogues.
This report audits apps/web, the legacy Next.js Pages Router application, as
it exists in the working tree on 2026-09-06. It records the access contract that
the Expo app and the experimental App Router catalogue should describe. It does
not treat pricing copy as enforcement unless a page or API checks the same rule.
Finding
Legacy has three customer tiers but five useful access states:
| Access ID | Meaning | Purchased? |
|---|---|---|
public | A guest can use the feature. | No |
account | A signed-in free account can use the feature. | No |
model | An active or trialing The Model subscription can use the feature. | £29.99/month |
ultra | An active or trialing The Model Ultra subscription can use the feature. | £59.99/month |
admin | The configured superadmin allowlist can use the feature. | No; this is an internal role. |
account and admin are not plans. They remain separate in configuration so
a login requirement is not mislabeled as a paywall and an internal route is not
advertised as purchasable.
Customer plans and legacy names
| Canonical plan | Price | Legacy database value | Other labels found in legacy |
|---|---|---|---|
| StatsHub | £0 | No active subscription | Free |
| The Model | £29.99/month | starter | Starter, Pro |
| The Model Ultra | £59.99/month | pro | Pro, Pro+, Pro+ All Access |
The pricing page defines the customer-facing names and prices in
apps/web/src/pages/pricing.tsx:131-164. Stripe stores starter for the
£29.99 product and pro for the £59.99 product
(apps/web/src/pages/api/stripe/webhook.ts:27-30). The account page then calls
those same values both Starter/Pro and Pro/Pro+ in different places
(apps/web/src/pages/account.tsx:156-190).
The forward-port contract uses model and ultra. The old storage values stay
as boundary aliases only; UI and feature configuration must not call the
£29.99 plan pro while also calling the £59.99 plan pro.
What each customer tier receives
StatsHub
The public research surface includes player and team statistics, form,
head-to-head data, Trends, Prop Screener, referee data, fixtures, leagues,
Outliers, Lineups, 100 Club, and the ordinary detail pages. The pricing matrix
lists the core subset at apps/web/src/pages/pricing.tsx:92-96.
A free account adds personal state and removes guest previews:
- full PropHunter results; guests receive four blurred results;
- saved PropHunter presets;
- player and team favourites and their notes;
- Prop Screener and 100 Club watchlists;
- saved filters and bookmaker preferences;
- account and subscription-management pages.
These are account capabilities, not model capabilities. In particular,
PropHunter contains no paid-subscription check. The guest result cap is in
apps/web/src/components/player-results-list.tsx:155-160,613-638.
The Model
Any active or trialing paid subscription passes the page-level gate for:
- Value Bets v2, v3, and v4;
- Macca's preconfigured scanner;
- fair odds, positive expected-value selections, and best-bookmaker prices;
- Team Models for shots, shots on target, and tackles;
- Bet Builder, including model-derived prices, correlated combined prices, lineup values, market anchoring, and Super Sub calculations;
- Super Sub Heroes and its statistic, league, and time-window leaderboards;
- Value Bet watchlists, tracking, and community reports;
- Telegram linking, Value Bet delivery, and lineup alerts;
- live foul and card alert activation.
The page-level split is explicit in
apps/web/src/pages/value-bets-v2.tsx:300-301,
apps/web/src/pages/bet-builder.tsx:1010-1014, and
apps/web/src/pages/super-sub-heroes.tsx:107-139. Those checks ask only whether
the subscription is active; they do not require the top tier.
The Model Ultra
Ultra inherits The Model and adds the transparent model-analysis surface:
- Raw Model Outputs in Value Bets v2 and v3;
- all model outputs and their time windows;
- detailed bookmaker comparison;
- the Value Bets v4 model-edge matrix;
- the richer Value Bet card treatment in the v2 watchlist.
Legacy implements this as a second check for stored tier pro. The v2 view
labels Raw Model Outputs as “All models, time windows & bookmaker comparison”
and redirects a lower-tier subscriber to pricing
(apps/web/src/pages/value-bets-v2.tsx:2193-2217). V4 describes the £59.99
addition as the model-edge matrix
(apps/web/src/components/value-bets-v4/view-as.tsx:28-42).
Superadmin
Payment does not unlock the superadmin surface. It includes:
- the legacy
/value-bets,/AGS, and/Player-Cardsroutes; /assistant, whose data endpoint rejects ordinary signed-in accounts;/tipster/*and/superadmin/*;- Value Bets v4 matchup grades and the over/under direction switch;
- administrative lineup analysis and operational tools.
Superadmins also bypass ordinary subscription gates. The role should therefore satisfy lower access requirements at runtime without being represented as a fourth purchasable plan.
Feature configuration matrix
The shared catalogue now records the following minimum access. “Platform-only” means the tool has no reliable legacy customer rule, so its current public classification is retained instead of inventing a paywall.
| Feature ID | Minimum access | Evidence or decision |
|---|---|---|
home | public | Legacy homepage and matchday data are public. |
teams, players, fixtures | public | Public lookup pages. |
fixture, team | public | Public detail data; favourite actions are account-only. |
matches, trends, screener | public | Public boards. Screener watchlist is separately account. |
picks | model | This entry describes saved bets tracked to settlement, which lived inside paid Value Bets. It remains hidden. |
value-bets | admin | The old route is protected as a superadmin route and remains hidden. |
value-bets-v2, value-bets-v3 | model | Both paid plans open their main scanner and Team Models. |
| Raw Model Outputs | ultra | Explicit stored-tier pro check. |
bet-builder | model | Any active paid plan passes. |
outliers | public | Legacy navigation said Pro, but its page and API were public. |
prophunter | account | Guests receive a capped preview; a free account opens the full tool. |
ags, player-cards, assistant | admin | Legacy routes or usable backend are superadmin-only. |
assist, 100-club, player-trends, build-ups | public | No paid gate. 100 Club save actions remain account-only. |
super-sub-heroes | model | Page and API require an active paid plan. |
leagues, referees, lineups | public | No paid gate. |
lineup-bot | public | The landing page is public. It sells a separate Telegram subscription, not a StatsHub model tier. |
odds-api | public | Public sales page; commercial API access is a separate product. |
fouls-alerts | model | The page needs an account and activation needs an active paid plan. |
datavisualiser, odds-converter | public | No legacy model-tier gate; Data Visualiser remains hidden. |
favourites | account | Login-only personal data, without a paid-subscription check. |
Pricing claims that are not separate gates
The pricing page says The Model is “Game Day Only” and Ultra includes “Full
slate, days ahead.” Those phrases appear in the pricing matrix but no tier check
restricts fixture dates elsewhere in apps/web/src. Paid viewers can reach the
same page-level data flows regardless of starter or pro.
The following are also marketing descriptions rather than independently enforced capabilities:
- Private Sharps Chat has no subscription provisioning or join flow in the web application.
- Early access has no tier-aware feature flag.
- Consensus picks, extra filters, and extra windows are exposed through the Ultra-only detailed model view rather than checked as separate entitlements.
The alternate /pricing/3-tier page advertises Core, Sharp, and Sharp Pro. Its
buttons only lead to signup, while the Stripe checkout allowlist accepts the
two real monthly price IDs. It is an experimental pricing design, not a third
working billing model.
Subscription state
Access is active when the latest subscription is active or trialing, is not
paused, and meets the feature's minimum tier. Superadmins bypass those billing
checks. A subscription scheduled to cancel at period end remains active until
its period ends.
The Pages Router server helper now applies the same pause and tier checks as
the browser. The Go API accepts the legacy starter and pro values as
boundary aliases for Model and Ultra, and also accepts the canonical model
and ultra values.
Configuration applied to the replacement clients
Both catalogues now contain:
- the three canonical plan records and their legacy Stripe aliases;
- the five-value minimum-access vocabulary;
- feature-level
public,account,model, andadminclassifications; ultraon the Raw Model Outputs routes;accounton the Prop Screener watchlist;- a public classification for the separately sold Lineup Bot landing page.
The copies live at apps/expo/src/lib/config and
apps/web-app-router/src/lib/config. Config tests pin the plan names, prices,
stored aliases, and the access boundaries most likely to regress.
The catalogue also drives runtime enforcement:
- Expo maps Model and Ultra to separate RevenueCat entitlements. Ultra inherits Model access. Route guards cover configured launches and direct links, while the API prevents a lower tier from loading Raw Model Outputs.
- The experimental App Router enables its premium gates. Value Bets v2 and v3 stop raw-output requests for a lower-tier subscriber.
- Both the Pages Router API and Go API require Model for
mode=scannerand Ultra formode=detailedor an unqualified raw-output request. Value Bets v4 and the generation-one raw model endpoint require Ultra. - Model-only consumers such as Bet Builder now request scanner mode explicitly.
The Expo defaults retain StatsHub Pro as the Model entitlement identifier for
existing RevenueCat projects. Ultra defaults to StatsHub Ultra; deployments
can set EXPO_PUBLIC_REVENUECAT_MODEL_ENTITLEMENT and
EXPO_PUBLIC_REVENUECAT_ULTRA_ENTITLEMENT when dashboard identifiers differ.
Evidence limits
This is a source and local API audit, not a production billing audit. The RevenueCat dashboard must define both entitlements and attach them to the right products; source code cannot create that external configuration. Stripe products, RevenueCat offerings, remote flags, and production database records were not queried. The repository already contained extensive uncommitted work; this report does not attribute or assess those unrelated changes.
Related
Database query performance audit — 2026-09-02
Measured results from the v1 and v2 API query audit, including the accepted optimizations, rejected experiments, response-size findings, parity evidence, and Redis recommendation.
Monorepo overview
A map of the StatsHub apps, shared packages, task graph, and ownership boundaries.