Skip to content

feat(catalog): eligibility-gated free-tier bucket - #12669

Merged
diegosouzapw merged 30 commits into
release/v3.8.51from
feat/free-tier-gated-bucket
Sep 4, 2026
Merged

diegosouzapw merged 30 commits into
release/v3.8.51from
feat/free-tier-gated-bucket

Conversation

@diegosouzapw

@diegosouzapw diegosouzapw commented Sep 4, 2026 •

Copy link
Copy Markdown
Owner

Summary

Adds a second, honest free-tier figure to the catalog: quotas that are real and recurring but only
open after a region-bound identity check (today: ModelScope, behind Alibaba Cloud binding +
mainland-China real-name verification). Decisions D1/D4 of the "free-tier honest growth" plan:

  • D1 — one honest headline. The steady headline stays the pool-deduped number computed from the
    catalog; a gated quota never inflates it.
  • D4 — a separate, CI-gated figure. The gated total is exposed as gatedRecurringTokens /
    gatedProviders, rendered apart on the dashboard, and validated by npm run check:docs-counts
    against the docs (anchor: behind regional identity verification).

The regime is untouched: eligibilityGate is an orthogonal field, freeType and every budget
stay as they were, so routing behavior is unchanged by this PR.

What changed

  • Catalog — new optional eligibilityGate field on free-model rows ("regional-identity"
    today) and two new totals from computeFreeModelTotals(): gatedRecurringTokens and
    gatedProviders. Gated rows are pool-deduped with the same rule as the steady bucket and are
    excluded from steadyRecurringTokens.
  • ModelScope — 2 rows added, pool modelscope-free, 6,000,000 tokens/mo (250 魔粒/day → 6M/mo),
    freeType: recurring-daily, tos: caution, eligibilityGate: regional-identity, with an
    // evidence: comment citing the provider's own page.
  • Docs gate — check-docs-counts-sync now validates the gated line alongside the steady/pool
    claims, so the "+~6M behind regional identity verification" sentence cannot drift.
  • Budget-card SVG generator — scripts/research/gen-budget-card-svg.mjs rewritten to read
    computeFreeModelTotals() instead of regex-parsing the catalog file. The old regex silently
    skipped 20 rows and printed 1.44B; the generator now emits the real totals plus a gated
    line. docs/screenshots/free-tier-budget-card.svg is regenerated from it.
  • Dashboard — FreeBudgetCard renders the gated figure as a callout under the headline, behind
    the new i18n key freeBudget.gated (translated in vi; 39 locales carry the usual
    __MISSING__ sentinel until the translation batch runs).
  • Radar feed — eligibilityGate carried through the feed schema, applyFeed() merge and the
    /api/free-tier/summary passthrough, with the documented semantics: absent preserves,
    null clears, override wins.
  • FREE_TIERS.md — TL;DR row for the gated bucket, an "Eligibility-gated quotas" methodology
    bullet, and a new "Why our number is smaller than other aggregators'" section explaining the
    pool-dedupe rule (our own catalog summed per model would read ~7.4B).
  • A companion radar-server PR follows separately (feed producer side).

Numbers (live, from computeFreeModelTotals() on this branch)

Metric Value
Steady recurring 1,473,225,000 (~1.47B) — unchanged by this PR
First month (with signup credits) 2,099,725,000 (~2.10B)
Gated (new) 6,000,000 (modelscope)
Catalog entries 444 (437 active + 7 discontinued)
Recurring pool keys 34
Free-forever providers 52 — gated providers excluded from the free-forever set by this PR (was 53)

The ~1.47B/2.10B figures come from PR1 + the base's #12591 (Cerebras reclassified as a one-time $5
signup credit); this PR moves neither.

Note on free-forever = 52 (was 53): the gate used to build that set from freeType alone, so
the gated provider was counted as "free forever" even though its tokens are not in the headline.
This PR excludes eligibility-gated rows from the set, so every headline-adjacent figure — steady,
first month, credits, uncapped list and free-forever — now honors the gate consistently.

Depends on

Depends on #12649 (PR1, the free-tier quota re-audit) — this branch already contains it
(merged in, conflicts resolved, numbers re-synced through the gate).

Validation

Check Result
npm run check:docs-counts exit 0
npm run check:docs-sync exit 0
npm run check:provider-consistency exit 0
npm run typecheck:core exit 0
npm run check:dashboard-typecheck exit 0
Focused unit tests (15 files, node:test) 203 pass / 0 fail
npx vitest run tests/unit/ui/free-budget-card-gated.test.tsx 2 pass
npm run i18n:check-ui-coverage exit 0
ESLint (with suppressions) on the 23 changed .ts/.tsx) 0 errors

Focused tests run: free-model-catalog-gated-bucket, free-tier-reaudit-2026-09,
free-providers-batch-2026-07, check-docs-counts-sync, gen-budget-card-svg,
radar-feed-eligibility-gate, radar-apply-feed, radar-localized-feed, radar-sync,
free-tier-summary-radar-overlay, free-tier-summary-route, free-model-catalog,
free-tier-catalog, i18n-vi-completeness, removed-providers-blocklist.

Full suites and the production build are left to CI.

⚠️ base-red inherited: #12581

Follow-ups

  • The "~7.4B unsummed" comparison figure in FREE_TIERS.md is not CI-gated — re-measure it
    whenever the catalog changes (a note next to it says so).
  • ModelScope model ids were validated against modelscope.cn's model API, not the API-Inference
    /v1/models list (needs a key) — confirm one id live before enabling routing by default.
  • The vi translations of the new i18n strings need a native-speaker review.
  • Pre-existing: FreeBudgetCard contains a hardcoded Chinese literal (not introduced here).

CI triage (run 33831114014 on ed1bc26, base release/v3.8.51 @ c41ec7f)

Check Verdict
Docs Gates (fast-path), Vitest (fast-path), Change Classification, No new ESLint warnings, semgrep green
Unit Tests fast-path — free-catalog-no-confidence-field rejected the new eligibilityGate key ours, fixed in ed1bc26 (key registered in the allowlist: it says who may claim a quota, not how much a row can be trusted)
Fast Quality Gates / API Route Typecheck — open-sse/executors/glm.ts TS2554 inherited (#12179 on the base; not in this diff)
Fast Quality Gates — mutation-test-coverage: tests/unit/reset-aware-request-scope-12600.test.ts missing from stryker.conf.json inherited (#12600/#12637 landed on the base after this branch; file not in this diff)
Fast Quality Gates — complexity-ratchets open-sse/services/genericQuotaFetcher.ts 0 → 1 inherited: the file is not in this diff (base moved 25 commits since the merge-base)
Merge integrity — changelog.d/fixes/reset-aware-model-family.md must start with a bullet inherited (fragment from #12637 on the base; not in this diff)
Unit Tests fast-path (1–4/4) — 16 failing tests (stream-failure sanitization, credential redaction, HuggingChat/Kiro/codex-image boundaries, model-sync route) inherited: the same set fails on #12649's final run and on unrelated branches (runs 33825690606, 33825612505); none of the files are in this diff

diegosouzapw and others added 28 commits September 2, 2026 10:24
…ier-quota-reaudit

# Conflicts:
#	README.md
#	docs/diagrams/readme-hero.svg
#	src/i18n/messages/in.json
…ier-quota-reaudit

# Conflicts:
#	README.md
#	docs/diagrams/free-tier-budget.svg
#	docs/diagrams/readme-hero.svg
#	open-sse/config/freeModelCatalog.data.ts
…bucket

# Conflicts:
#	src/i18n/messages/in.json
…ier-quota-reaudit

# Conflicts:
#	README.md
#	docs/diagrams/README.md
#	docs/diagrams/free-tier-budget.svg
#	docs/diagrams/readme-hero.svg
#	docs/getting-started/FREE-TIERS-GUIDE.md
#	docs/reference/FREE_TIERS.md
#	open-sse/config/freeTierCatalog.ts
#	tests/unit/free-tier-catalog.test.ts
…bucket

# Conflicts:
#	README.md
#	docs/diagrams/README.md
#	docs/diagrams/free-tier-budget.svg
#	docs/diagrams/promise-pillars.svg
#	docs/diagrams/readme-hero.svg
#	docs/getting-started/FREE-TIERS-GUIDE.md
#	docs/reference/FREE_TIERS.md
#	docs/screenshots/free-tier-budget-card.svg
#	open-sse/config/freeTierCatalog.ts
#	tests/unit/free-tier-catalog.test.ts
#	tests/unit/free-tier-reaudit-2026-09.test.ts
…ent figure

The eligibility gate was honored by the steady headline and the pool count, but
three adjacent figures still counted gated rows: the credit reductions feeding
steadyWithRecurringCreditsTokens/firstMonthRealisticTokens, the uncappedProviders
list ("permanently free, no cap"), and the docs gate's free-forever provider set,
which was built from freeType alone.

- computeFreeModelTotals: filter !isGated in the recurring-credit, one-time-credit
  and uncapped predicates; gatedProviders semantics unchanged (steady rows only).
- check-docs-counts-sync: exclude eligibility-gated rows from the FOREVER set,
  which moves the live free-forever count 53 -> 52 (the base's value). README,
  promise-pillars.svg and FREE-TIERS-GUIDE re-synced.
- gen-budget-card-svg: skip gated one-time credits like the totals do, and fail
  loudly on `--out` without a path.
- Tests: gated one-time credit does not move firstMonthRealisticTokens; a gated
  uncapped row is not in uncappedProviders; shipped gated rows carry no credit
  tokens; the committed budget card is byte-identical to a fresh generation.
…bucket

# Conflicts:
#	docs/reference/FREE_TIERS.md
@diegosouzapw
diegosouzapw changed the base branch from fix/free-tier-quota-reaudit to release/v3.8.51 September 4, 2026 02:26
…tier-gated-bucket

# Conflicts:
#	README.md
#	docs/diagrams/free-tier-budget.svg
#	docs/getting-started/FREE-TIERS-GUIDE.md
#	docs/reference/FREE_TIERS.md
#	tests/unit/free-tier-reaudit-2026-09.test.ts
…owlist

The allowlist landed on the base with #12318, after this branch's field was designed;
eligibilityGate says who may claim a quota, not how much a row can be trusted.
@diegosouzapw
diegosouzapw merged commit 488f57e into release/v3.8.51 Sep 4, 2026
14 of 21 checks passed
diegosouzapw added a commit to PixmaNts/OmniRoute that referenced this pull request Sep 4, 2026
Keep Lyceum on top of the later catalog/docs tip, including diegosouzapw#12669
eligibility-gated free-tier. Provider count 356 -> 357; restore i18n
llm.txt five-part mirror headers; keep origin's ~1.47B / 52 free-forever
headline (Lyceum is pay-per-use, not in the free-budget catalog).

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
diegosouzapw added a commit to jeanbispo/OmniRoute that referenced this pull request Sep 4, 2026
Keep notrack-web and the later catalog (diegosouzapw#12669 eligibility-gated
free-tier + SeekAi). Live count is 357 providers / 444 free-tier
entries. Align unique catalog/docs/i18n counts with a notrack-web
specific assert.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
diegosouzapw added a commit to jackjinke/OmniRoute that referenced this pull request Sep 4, 2026
Preserve BigModel.cn next to SeekAi and diegosouzapw#12669's eligibility-gated
free-tier catalog (~1.47B / 52 free-forever). Live unique counts stay
APIKEY 239, reserved prefixes 409, providers 357, with BigModel-specific
asserts.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
diegosouzapw added a commit to Abhishekchhetri020/OmniRoute that referenced this pull request Sep 4, 2026
Keep Gemini 3.8 Flash high/medium/low on the eligibility-gated free-tier
catalog from diegosouzapw#12669, and align unique docs/SVG counts to 447 entries.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
* test(catalog): pin the 2026-09-02 free-tier re-audit facts for gemini, ollama-cloud, groq, nara and mistral

* fix(catalog): re-audit gemini, ollama-cloud, groq, nara and mistral against official pages

* fix(catalog): restore the console-verified Mistral 1B pool and harden its regression test

* docs(free-tiers): move headline to the re-audited ~1.50B and refresh pool counts

* chore(free-tiers): retire stale Groq free-tier text and preset model; fix catalog header

* feat(catalog): eligibilityGate field and gatedRecurringTokens total

* docs(free-tiers): state the evidence-comment rule honestly and retire the last "14.4K RPD" Groq texts

* feat(check): docs-counts gate validates the eligibility-gated free-tier figure

* fix(docs): budget card reads computeFreeModelTotals() instead of regex-parsing the catalog

* docs(free-tiers): retire the stale Gemini onboarding quota text

* feat(radar): carry eligibilityGate through the feed schema, the merge and the summary API

* feat(dashboard): show the eligibility-gated free-tier figure apart from the headline

* docs(free-tier): refresh catalog-entry counts to 442 after base sync

* feat(catalog): ModelScope as the first eligibility-gated pool; document the gated bucket and how we count

* docs(free-tiers): restore README spacing lost in the merge and re-sync the guide counts

* docs(free-tiers): correct the unsummed-catalog comparison figure to the current catalog

* docs(free-tiers): re-sync numbers after merging release/v3.8.51 (Cerebras reclassified upstream)

* docs(free-tiers): re-sync numbers after merging PR1 (Cerebras reclassified upstream)

* fix(docs): keep the NaraRouter plans endpoint out of the API-path checker; rebaseline gateways.ts (+3)

* fix(catalog): keep eligibility-gated rows out of every headline-adjacent figure

The eligibility gate was honored by the steady headline and the pool count, but
three adjacent figures still counted gated rows: the credit reductions feeding
steadyWithRecurringCreditsTokens/firstMonthRealisticTokens, the uncappedProviders
list ("permanently free, no cap"), and the docs gate's free-forever provider set,
which was built from freeType alone.

- computeFreeModelTotals: filter !isGated in the recurring-credit, one-time-credit
  and uncapped predicates; gatedProviders semantics unchanged (steady rows only).
- check-docs-counts-sync: exclude eligibility-gated rows from the FOREVER set,
  which moves the live free-forever count 53 -> 52 (the base's value). README,
  promise-pillars.svg and FREE-TIERS-GUIDE re-synced.
- gen-budget-card-svg: skip gated one-time credits like the totals do, and fail
  loudly on `--out` without a path.
- Tests: gated one-time credit does not move firstMonthRealisticTokens; a gated
  uncapped row is not in uncappedProviders; shipped gated rows carry no credit
  tokens; the committed budget card is byte-identical to a fresh generation.

* test(catalog): allow eligibilityGate in the no-per-row-rating key allowlist

The allowlist landed on the base with diegosouzapw#12318, after this branch's field was designed;
eligibilityGate says who may claim a quota, not how much a row can be trusted.

---------

Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
Co-authored-by: diegosouzapw <diegosouzapw24@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant