From cef066c4c55808380ce1a5b126e335b74d608dd7 Mon Sep 17 00:00:00 2001 From: Chris Taylor Date: Mon, 31 Aug 2026 11:30:20 +0100 Subject: [PATCH 1/2] Remove the image challenge threshold from the statistics page The row was added in 1.20.5 but renders an em dash for every install: the value lives on the upper rung of the frictionless ladder, and the WordPress endpoint still sends frictionlessThreshold as a bare number, so there is nothing to show and no date by which there will be. Reverts the row, its label and its level helper. The statistics page is byte-identical to 1.20.4 again. The schema union is kept deliberately. It is not part of displaying the value: the portal has moved frictionlessThreshold to the ladder object, and because the whole site response is a single parse, a ladder arriving at a bare z.number() would fail and take out the entire statistics tab rather than one row. Co-Authored-By: Claude Opus 5 (1M context) --- .../src/settings/procaptcha/procaptchaSite.ts | 81 +++++++------------ .../statistics/components/appComponent.tsx | 43 ---------- assets/src/settings/statistics/config.ts | 4 - prosopo-procaptcha/prosopo-procaptcha.php | 2 +- prosopo-procaptcha/readme.txt | 5 +- .../Statistics/Statistics_Settings_Tab.php | 13 ++- 6 files changed, 42 insertions(+), 106 deletions(-) diff --git a/assets/src/settings/procaptcha/procaptchaSite.ts b/assets/src/settings/procaptcha/procaptchaSite.ts index f7982a0..43659a2 100644 --- a/assets/src/settings/procaptcha/procaptchaSite.ts +++ b/assets/src/settings/procaptcha/procaptchaSite.ts @@ -22,16 +22,6 @@ export interface SiteSettings { * plugin has always shown as "Frictionless Threshold". */ frictionlessThreshold: number; - /** - * Upper rung: the score at or above which a session gets an image captcha - * rather than a puzzle. Arrives nested inside `frictionlessThreshold`, not - * as a sibling of it, and is absent whenever that field is still the bare - * number the pre-ladder API sends. - * - * Not to be confused with the settings' own `imageThreshold`, which is an - * unrelated image-captcha setting on a 0..1 scale. - */ - frictionlessImageThreshold?: number; powDifficulty: number; captchaType: string; domains: string[]; @@ -44,16 +34,13 @@ export interface CaptchaUsage { } /** - * `SiteSettings` as it arrives on the wire, before the ladder is split into - * the two flat fields the rest of the plugin reads. Declared separately - * because the schema below transforms on parse, so its input and output - * types differ and `ZodType` needs both. + * `SiteSettings` as it arrives on the wire, before the ladder is collapsed to + * the single number the rest of the plugin reads. Declared separately because + * the schema below transforms on parse, so its input and output types differ + * and `ZodType` needs both. */ export interface SiteSettingsInput - extends Omit< - SiteSettings, - "frictionlessThreshold" | "frictionlessImageThreshold" - > { + extends Omit { frictionlessThreshold: | number | { @@ -77,40 +64,34 @@ const DEFAULT_FRICTIONLESS_THRESHOLD = 0.5; * `frictionlessThreshold` is read as "number, or the two-rung ladder object" * because both are live at once: the portal moved the field to the ladder, * but records migrate in the background and the plugin ships independently - * of the portal, so an install can be talking to either shape. A bare number - * means what it always meant — the puzzle rung — and carries no image rung. + * of the portal, so an install can be talking to either shape. + * + * The plugin only displays the puzzle rung, so the ladder collapses to it and + * the image rung is ignored. The union still has to be here: without it a + * ladder object fails `z.number()`, and because the whole site response is one + * parse, that failure takes out the entire statistics tab rather than one row. */ -const frictionlessThresholdSchema = z.union([ - z.number(), - z.object({ - frictionlessPuzzleThreshold: z.number().optional(), - frictionlessImageThreshold: z.number().optional(), - }), -]); +const frictionlessThresholdSchema = z + .union([ + z.number(), + z.object({ + frictionlessPuzzleThreshold: z.number().optional(), + frictionlessImageThreshold: z.number().optional(), + }), + ]) + .transform((value) => + "number" === typeof value + ? value + : (value.frictionlessPuzzleThreshold ?? + DEFAULT_FRICTIONLESS_THRESHOLD), + ); -/** - * Split the ladder into the two flat fields the rest of the plugin reads, so - * nothing downstream has to know which of the two wire shapes arrived. - */ -export const siteSettingsSchema = z - .object({ - frictionlessThreshold: frictionlessThresholdSchema, - powDifficulty: z.number(), - captchaType: z.string(), - domains: z.string().array(), - }) - .transform(({ frictionlessThreshold, ...settings }) => ({ - ...settings, - frictionlessThreshold: - "number" === typeof frictionlessThreshold - ? frictionlessThreshold - : (frictionlessThreshold.frictionlessPuzzleThreshold ?? - DEFAULT_FRICTIONLESS_THRESHOLD), - frictionlessImageThreshold: - "number" === typeof frictionlessThreshold - ? undefined - : frictionlessThreshold.frictionlessImageThreshold, - })) satisfies ZodType; +export const siteSettingsSchema = z.object({ + frictionlessThreshold: frictionlessThresholdSchema, + powDifficulty: z.number(), + captchaType: z.string(), + domains: z.string().array(), +}) satisfies ZodType; export const captchaUsageSchema = z.object({ submissions: z.number(), diff --git a/assets/src/settings/statistics/components/appComponent.tsx b/assets/src/settings/statistics/components/appComponent.tsx index 9f25eca..e2fc253 100644 --- a/assets/src/settings/statistics/components/appComponent.tsx +++ b/assets/src/settings/statistics/components/appComponent.tsx @@ -122,11 +122,6 @@ class AppComponent extends React.Component { .frictionlessThreshold, value: "...", }, - { - label: this.config.getCaptchaSettingsLabels() - .frictionlessImageThreshold, - value: "...", - }, { label: this.config.getCaptchaSettingsLabels() .powDifficulty, @@ -226,37 +221,6 @@ class AppComponent extends React.Component { return frictionlessThreshold < 0.4 ? levelLabels.high : levelLabels.low; } - /** - * Upper rung of the score ladder, shown as a level rather than a raw - * score to match its sibling above. A lower rung means more sessions - * reach an image captcha instead of a puzzle, so it reads as stricter. - * - * Banded on the portal's 1.0 default rather than a range: unlike the - * lower rung this one is deliberately allowed above 1, because the score - * it is compared against is a total that server-side penalties add to. - * - * An API still sending the pre-ladder bare `frictionlessThreshold` gives - * no upper rung at all, in which case the row shows an em dash rather - * than inventing a value. - */ - protected getFrictionlessImageThresholdLabel( - frictionlessImageThreshold: number | undefined, - ): string { - if (undefined === frictionlessImageThreshold) { - return "—"; - } - - const levelLabels = this.config.getCaptchaSettingsLabels().level; - - if (frictionlessImageThreshold < 1) { - return levelLabels.high; - } - - return 1 === frictionlessImageThreshold - ? levelLabels.normal - : levelLabels.low; - } - protected getTypeLabel(type: string): string { const typeLabels = this.config.getCaptchaSettingsLabels().types; @@ -296,13 +260,6 @@ class AppComponent extends React.Component { siteSettings.frictionlessThreshold, ), }, - { - label: this.config.getCaptchaSettingsLabels() - .frictionlessImageThreshold, - value: this.getFrictionlessImageThresholdLabel( - siteSettings.frictionlessImageThreshold, - ), - }, { label: this.config.getCaptchaSettingsLabels() .powDifficulty, diff --git a/assets/src/settings/statistics/config.ts b/assets/src/settings/statistics/config.ts index 82c6ee1..6e5d621 100644 --- a/assets/src/settings/statistics/config.ts +++ b/assets/src/settings/statistics/config.ts @@ -24,7 +24,6 @@ interface CaptchaSettingsLabels { title: string; type: string; frictionlessThreshold: string; - frictionlessImageThreshold: string; powDifficulty: string; level: { low: string; @@ -152,9 +151,6 @@ class ConfigClass implements Config { frictionlessThreshold: captchaSettingsLabels.getString( "frictionlessThreshold", ), - frictionlessImageThreshold: captchaSettingsLabels.getString( - "frictionlessImageThreshold", - ), powDifficulty: captchaSettingsLabels.getString("powDifficulty"), level: { low: level.getString("low"), diff --git a/prosopo-procaptcha/prosopo-procaptcha.php b/prosopo-procaptcha/prosopo-procaptcha.php index f2b1601..813d411 100644 --- a/prosopo-procaptcha/prosopo-procaptcha.php +++ b/prosopo-procaptcha/prosopo-procaptcha.php @@ -2,7 +2,7 @@ /** * Plugin Name: Prosopo Procaptcha * Description: GDPR compliant, privacy friendly and better value captcha. - * Version: 1.20.5 + * Version: 1.20.6 * Author: Prosopo Team * Author URI: https://prosopo.io/ * License: GPLv2 or later diff --git a/prosopo-procaptcha/readme.txt b/prosopo-procaptcha/readme.txt index d434ff1..107babd 100644 --- a/prosopo-procaptcha/readme.txt +++ b/prosopo-procaptcha/readme.txt @@ -4,7 +4,7 @@ Tags: Captcha, Procaptcha, antispam, anibot, spam. Requires at least: 5.5 Tested up to: 6.9 Requires PHP: 7.4 -Stable tag: 1.20.5 +Stable tag: 1.20.6 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html @@ -135,6 +135,9 @@ Absolutely! The plugin has a [public GitHub repository](https://github.com/proso == Changelog == += 1.20.6 (2026-08-31) = +* Maintenance: remove the image challenge threshold from the statistics page + = 1.20.5 (2026-08-31) = * Feature: show the frictionless score ladder's image challenge threshold on the statistics page diff --git a/prosopo-procaptcha/src/Settings/Statistics/Statistics_Settings_Tab.php b/prosopo-procaptcha/src/Settings/Statistics/Statistics_Settings_Tab.php index b528499..25314cf 100644 --- a/prosopo-procaptcha/src/Settings/Statistics/Statistics_Settings_Tab.php +++ b/prosopo-procaptcha/src/Settings/Statistics/Statistics_Settings_Tab.php @@ -71,17 +71,16 @@ function ( Upgrade_Tier_Banner $model ) { ), 'callToUpgradeElementMarkup' => $call_to_upgrade_element_markup, 'captchaSettingsLabels' => array( - 'frictionlessImageThreshold' => __( 'Image Challenge Threshold:', 'prosopo-procaptcha' ), - 'frictionlessThreshold' => __( 'Frictionless Threshold:', 'prosopo-procaptcha' ), - 'level' => array( + 'frictionlessThreshold' => __( 'Frictionless Threshold:', 'prosopo-procaptcha' ), + 'level' => array( 'high' => __( 'High', 'prosopo-procaptcha' ), 'low' => __( 'Low', 'prosopo-procaptcha' ), 'normal' => __( 'Normal', 'prosopo-procaptcha' ), ), - 'powDifficulty' => __( 'Proof of Work Difficulty:', 'prosopo-procaptcha' ), - 'title' => __( 'Captcha Settings', 'prosopo-procaptcha' ), - 'type' => __( 'Type:', 'prosopo-procaptcha' ), - 'types' => array( + 'powDifficulty' => __( 'Proof of Work Difficulty:', 'prosopo-procaptcha' ), + 'title' => __( 'Captcha Settings', 'prosopo-procaptcha' ), + 'type' => __( 'Type:', 'prosopo-procaptcha' ), + 'types' => array( 'frictionless' => __( 'Frictionless', 'prosopo-procaptcha' ), 'image' => __( 'Image', 'prosopo-procaptcha' ), 'proofOfWork' => __( 'Proof of Work', 'prosopo-procaptcha' ), From f29e65ead34573b905910990683129bcab803202 Mon Sep 17 00:00:00 2001 From: Chris Taylor Date: Mon, 31 Aug 2026 11:37:55 +0100 Subject: [PATCH 2/2] Reduce the statistics page to captcha counts and the traffic chart MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drops the Account Information, Captcha Settings and Whitelisted Domains panels, leaving the monthly image/PoW counts and the traffic chart. Takes the throw risk out at the root rather than guarding against it. `settings` is no longer declared on the site schema at all, so zod strips it: the whole response is a single parse, and a field the page does not display has no business being able to fail it. That removes the frictionlessThreshold union, its transform, and the Input types that existed only to describe them. Also removes the now-orphaned ListComponent and the account, captcha settings and domain label sets on both the TS and PHP sides. Note: no puzzle count. The endpoint does not carry one — MonthlyCaptchaRequestsSchema is limit/image/pow/year/month — so showing it needs a portal change first. Co-Authored-By: Claude Opus 5 (1M context) --- .../src/settings/procaptcha/procaptchaSite.ts | 90 ++-------- .../statistics/components/appComponent.tsx | 167 +----------------- .../statistics/components/listComponent.tsx | 38 ---- assets/src/settings/statistics/config.ts | 88 +-------- prosopo-procaptcha/readme.txt | 2 +- .../Statistics/Statistics_Settings_Tab.php | 24 --- 6 files changed, 18 insertions(+), 391 deletions(-) delete mode 100644 assets/src/settings/statistics/components/listComponent.tsx diff --git a/assets/src/settings/procaptcha/procaptchaSite.ts b/assets/src/settings/procaptcha/procaptchaSite.ts index 43659a2..e322aa2 100644 --- a/assets/src/settings/procaptcha/procaptchaSite.ts +++ b/assets/src/settings/procaptcha/procaptchaSite.ts @@ -2,12 +2,20 @@ import { type ProcaptchaAccount, procaptchaAccountSchema, } from "#settings/procaptcha/procaptchaAccount.js"; -import { z, type ZodType, type ZodTypeDef } from "zod"; +import { z, type ZodType } from "zod"; +/** + * Only the parts of the site response the statistics page actually renders: + * the monthly captcha counts and the account tier the traffic chart gates on. + * + * `settings` is deliberately absent. Zod strips keys a schema does not + * declare, so whatever shape the portal sends for the captcha settings — and + * `frictionlessThreshold` has already changed shape once — is ignored rather + * than validated. The whole response is a single parse, so a field the page + * does not display has no business being able to fail it. + */ export interface ProcaptchaSite { account: ProcaptchaAccount; - name: string; - settings: SiteSettings; monthlyUsage: { limit: number; image: CaptchaUsage; @@ -15,84 +23,12 @@ export interface ProcaptchaSite { }; } -export interface SiteSettings { - /** - * Lower rung of the frictionless score ladder: the score a session has to - * stay under to pass without being challenged. This is the value the - * plugin has always shown as "Frictionless Threshold". - */ - frictionlessThreshold: number; - powDifficulty: number; - captchaType: string; - domains: string[]; -} - export interface CaptchaUsage { submissions: number; verifications: number; total: number; } -/** - * `SiteSettings` as it arrives on the wire, before the ladder is collapsed to - * the single number the rest of the plugin reads. Declared separately because - * the schema below transforms on parse, so its input and output types differ - * and `ZodType` needs both. - */ -export interface SiteSettingsInput - extends Omit { - frictionlessThreshold: - | number - | { - frictionlessPuzzleThreshold?: number; - frictionlessImageThreshold?: number; - }; -} - -export interface ProcaptchaSiteInput extends Omit { - settings: SiteSettingsInput; -} - -/** - * Fallback for a ladder object that arrives without its lower rung. Matches - * the portal's own default so the label the user sees does not change - * meaning between the two shapes. - */ -const DEFAULT_FRICTIONLESS_THRESHOLD = 0.5; - -/** - * `frictionlessThreshold` is read as "number, or the two-rung ladder object" - * because both are live at once: the portal moved the field to the ladder, - * but records migrate in the background and the plugin ships independently - * of the portal, so an install can be talking to either shape. - * - * The plugin only displays the puzzle rung, so the ladder collapses to it and - * the image rung is ignored. The union still has to be here: without it a - * ladder object fails `z.number()`, and because the whole site response is one - * parse, that failure takes out the entire statistics tab rather than one row. - */ -const frictionlessThresholdSchema = z - .union([ - z.number(), - z.object({ - frictionlessPuzzleThreshold: z.number().optional(), - frictionlessImageThreshold: z.number().optional(), - }), - ]) - .transform((value) => - "number" === typeof value - ? value - : (value.frictionlessPuzzleThreshold ?? - DEFAULT_FRICTIONLESS_THRESHOLD), - ); - -export const siteSettingsSchema = z.object({ - frictionlessThreshold: frictionlessThresholdSchema, - powDifficulty: z.number(), - captchaType: z.string(), - domains: z.string().array(), -}) satisfies ZodType; - export const captchaUsageSchema = z.object({ submissions: z.number(), verifications: z.number(), @@ -101,11 +37,9 @@ export const captchaUsageSchema = z.object({ export const procaptchaSiteSchema = z.object({ account: procaptchaAccountSchema, - name: z.string(), - settings: siteSettingsSchema, monthlyUsage: z.object({ limit: z.number(), image: captchaUsageSchema, pow: captchaUsageSchema, }), -}) satisfies ZodType; +}) satisfies ZodType; diff --git a/assets/src/settings/statistics/components/appComponent.tsx b/assets/src/settings/statistics/components/appComponent.tsx index e2fc253..9099a97 100644 --- a/assets/src/settings/statistics/components/appComponent.tsx +++ b/assets/src/settings/statistics/components/appComponent.tsx @@ -4,7 +4,6 @@ import { AppStatusComponentProperties, StatCurrentState, } from "./appStatusComponent.js"; -import { ListComponent, ListComponentProperties } from "./listComponent.js"; import { TrafficAnalyticsComponent, TrafficAnalyticsComponentProperties, @@ -21,10 +20,7 @@ import { import type Logger from "#utils/logger/logger.js"; import { type Config, ConfigClass } from "#settings/statistics/config.js"; import CaptchaUsageNumberUtils from "#settings/statistics/captchaUsage/captchaUsageNumberUtils.js"; -import type { - ProcaptchaSite, - SiteSettings, -} from "#settings/procaptcha/procaptchaSite.js"; +import type { ProcaptchaSite } from "#settings/procaptcha/procaptchaSite.js"; import type { ProcaptchaAccount } from "#settings/procaptcha/procaptchaAccount.js"; import { @@ -39,9 +35,6 @@ interface AppComponentProperties { interface AppState { statState: AppStatusComponentProperties; usageInfo: CaptchaUsageComponentProperties; - accountInformation: ListComponentProperties; - captchaSettings: ListComponentProperties; - domains: ListComponentProperties; trafficData: TrafficAnalyticsComponentProperties; } @@ -95,45 +88,6 @@ class AppComponent extends React.Component { }, labels: this.config.getUsageLabels(), }, - accountInformation: { - title: this.config.getAccountLabels().title, - icon: "icon-[material-symbols--account-circle]", - items: [ - { - label: this.config.getAccountLabels().tier, - value: "...", - }, - { - label: this.config.getAccountLabels().name, - value: "...", - }, - ], - }, - captchaSettings: { - title: this.config.getCaptchaSettingsLabels().title, - icon: "icon-[material-symbols--settings]", - items: [ - { - label: this.config.getCaptchaSettingsLabels().type, - value: "...", - }, - { - label: this.config.getCaptchaSettingsLabels() - .frictionlessThreshold, - value: "...", - }, - { - label: this.config.getCaptchaSettingsLabels() - .powDifficulty, - value: "...", - }, - ], - }, - domains: { - title: this.config.getDomainLabels().title, - icon: "icon-[material-symbols--domain]", - items: [], - }, trafficData: { accountTier: "", logger: this.logger, @@ -164,22 +118,9 @@ class AppComponent extends React.Component { })); } - protected refreshUserData(site: ProcaptchaSite): void { + protected refreshUsage(site: ProcaptchaSite): void { this.setState((actualState) => ({ ...actualState, - accountInformation: { - ...actualState.accountInformation, - items: [ - { - label: this.config.getAccountLabels().tier, - value: site.account.tier.toUpperCase(), - }, - { - label: this.config.getAccountLabels().name, - value: site.name, - }, - ], - }, usageInfo: { ...actualState.usageInfo, limits: { @@ -199,83 +140,6 @@ class AppComponent extends React.Component { })); } - protected getPowDifficultyLabel(powDifficulty: number): string { - const levelLabels = this.config.getCaptchaSettingsLabels().level; - - if (powDifficulty === 4) { - return levelLabels.normal; - } - - return powDifficulty < 4 ? levelLabels.low : levelLabels.high; - } - - protected getFrictionlessThresholdLabel( - frictionlessThreshold: number, - ): string { - const levelLabels = this.config.getCaptchaSettingsLabels().level; - - if (frictionlessThreshold >= 0.4 && frictionlessThreshold <= 0.6) { - return levelLabels.normal; - } - - return frictionlessThreshold < 0.4 ? levelLabels.high : levelLabels.low; - } - - protected getTypeLabel(type: string): string { - const typeLabels = this.config.getCaptchaSettingsLabels().types; - - switch (type) { - case "image": - return typeLabels.image; - case "pow": - return typeLabels.proofOfWork; - default: - return typeLabels.frictionless; - } - } - - protected refreshSiteSettings(siteSettings: SiteSettings): void { - const domains = siteSettings.domains - .filter((domain) => "*" !== domain) - .map((domain, index) => { - return { - label: "#" + (index + 1), - value: domain, - }; - }); - - this.setState((actualState) => ({ - ...actualState, - captchaSettings: { - ...actualState.captchaSettings, - items: [ - { - label: this.config.getCaptchaSettingsLabels().type, - value: this.getTypeLabel(siteSettings.captchaType), - }, - { - label: this.config.getCaptchaSettingsLabels() - .frictionlessThreshold, - value: this.getFrictionlessThresholdLabel( - siteSettings.frictionlessThreshold, - ), - }, - { - label: this.config.getCaptchaSettingsLabels() - .powDifficulty, - value: this.getPowDifficultyLabel( - siteSettings.powDifficulty, - ), - }, - ], - }, - domains: { - ...actualState.domains, - items: domains, - }, - })); - } - protected refreshTrafficData(account: ProcaptchaAccount): void { this.setState((actualState) => ({ ...actualState, @@ -295,8 +159,7 @@ class AppComponent extends React.Component { ); if (site) { - this.refreshUserData(site); - this.refreshSiteSettings(site.settings); + this.refreshUsage(site); this.refreshTrafficData(site.account); this.markAsLoaded(); @@ -318,14 +181,7 @@ class AppComponent extends React.Component { } public render() { - const { - statState, - usageInfo, - accountInformation, - captchaSettings, - domains, - trafficData, - } = this.state; + const { statState, usageInfo, trafficData } = this.state; return (
@@ -343,21 +199,6 @@ class AppComponent extends React.Component { image={usageInfo.image} pow={usageInfo.pow} /> - - - ; -} - -class ListComponent extends React.Component { - render() { - const { title, icon, items } = this.props; - - return ( - -
- {items.map((item, index) => ( - -

- {item.label} -

-

- {item.value} -

-
- ))} -
-
- ); - } -} - -export { ListComponent, ListComponentProperties }; diff --git a/assets/src/settings/statistics/config.ts b/assets/src/settings/statistics/config.ts index 6e5d621..5bf8d9c 100644 --- a/assets/src/settings/statistics/config.ts +++ b/assets/src/settings/statistics/config.ts @@ -1,11 +1,5 @@ import Collection from "./collection.js"; -interface AccountLabels { - title: string; - name: string; - tier: string; -} - interface UsageLabels { title: string; total: string; @@ -20,27 +14,6 @@ interface StateLabels { loading: string; } -interface CaptchaSettingsLabels { - title: string; - type: string; - frictionlessThreshold: string; - powDifficulty: string; - level: { - low: string; - normal: string; - high: string; - }; - types: { - proofOfWork: string; - image: string; - frictionless: string; - }; -} - -interface DomainLabels { - title: string; -} - interface TrafficDataLabels { title: string; chartTitle: string; @@ -55,16 +28,10 @@ interface Config { getSecretKey(): string; - getAccountLabels(): AccountLabels; - getUsageLabels(): UsageLabels; getStateLabels(): StateLabels; - getCaptchaSettingsLabels(): CaptchaSettingsLabels; - - getDomainLabels(): DomainLabels; - getTrafficDataLabels(): TrafficDataLabels; getCallToUpgradeElementMarkup(): string; @@ -101,16 +68,6 @@ class ConfigClass implements Config { return this.data.getString("secretKey"); } - public getAccountLabels(): AccountLabels { - const accountLabels = this.data.getSubCollection("accountLabels"); - - return { - title: accountLabels.getString("title"), - name: accountLabels.getString("name"), - tier: accountLabels.getString("tier"), - }; - } - public getUsageLabels(): UsageLabels { const usageLabels = this.data.getSubCollection("usageLabels"); @@ -137,42 +94,6 @@ class ConfigClass implements Config { }; } - public getCaptchaSettingsLabels(): CaptchaSettingsLabels { - const captchaSettingsLabels = this.data.getSubCollection( - "captchaSettingsLabels", - ); - - const level = captchaSettingsLabels.getSubCollection("level"); - const types = captchaSettingsLabels.getSubCollection("types"); - - return { - title: captchaSettingsLabels.getString("title"), - type: captchaSettingsLabels.getString("type"), - frictionlessThreshold: captchaSettingsLabels.getString( - "frictionlessThreshold", - ), - powDifficulty: captchaSettingsLabels.getString("powDifficulty"), - level: { - low: level.getString("low"), - normal: level.getString("normal"), - high: level.getString("high"), - }, - types: { - proofOfWork: types.getString("proofOfWork"), - image: types.getString("image"), - frictionless: types.getString("frictionless"), - }, - }; - } - - public getDomainLabels(): DomainLabels { - const domainLabels = this.data.getSubCollection("domainLabels"); - - return { - title: domainLabels.getString("title"), - }; - } - public getTrafficDataLabels(): TrafficDataLabels { const trafficDataLabels = this.data.getSubCollection("trafficDataLabels"); @@ -196,11 +117,4 @@ class ConfigClass implements Config { } } -export { - Config, - ConfigClass, - AccountLabels, - UsageLabels, - StateLabels, - TrafficDataLabels, -}; +export { Config, ConfigClass, UsageLabels, StateLabels, TrafficDataLabels }; diff --git a/prosopo-procaptcha/readme.txt b/prosopo-procaptcha/readme.txt index 107babd..1393d51 100644 --- a/prosopo-procaptcha/readme.txt +++ b/prosopo-procaptcha/readme.txt @@ -136,7 +136,7 @@ Absolutely! The plugin has a [public GitHub repository](https://github.com/proso == Changelog == = 1.20.6 (2026-08-31) = -* Maintenance: remove the image challenge threshold from the statistics page +* Maintenance: simplify the statistics page to the monthly captcha counts and the traffic chart = 1.20.5 (2026-08-31) = * Feature: show the frictionless score ladder's image challenge threshold on the statistics page diff --git a/prosopo-procaptcha/src/Settings/Statistics/Statistics_Settings_Tab.php b/prosopo-procaptcha/src/Settings/Statistics/Statistics_Settings_Tab.php index 25314cf..155b5ee 100644 --- a/prosopo-procaptcha/src/Settings/Statistics/Statistics_Settings_Tab.php +++ b/prosopo-procaptcha/src/Settings/Statistics/Statistics_Settings_Tab.php @@ -64,31 +64,7 @@ function ( Upgrade_Tier_Banner $model ) { return array( 'accountApiEndpoint' => Procaptcha_Plugin::ACCOUNT_API_ENDPOINT_URL, - 'accountLabels' => array( - 'name' => __( 'Name:', 'prosopo-procaptcha' ), - 'tier' => __( 'Tier:', 'prosopo-procaptcha' ), - 'title' => __( 'Account Information', 'prosopo-procaptcha' ), - ), 'callToUpgradeElementMarkup' => $call_to_upgrade_element_markup, - 'captchaSettingsLabels' => array( - 'frictionlessThreshold' => __( 'Frictionless Threshold:', 'prosopo-procaptcha' ), - 'level' => array( - 'high' => __( 'High', 'prosopo-procaptcha' ), - 'low' => __( 'Low', 'prosopo-procaptcha' ), - 'normal' => __( 'Normal', 'prosopo-procaptcha' ), - ), - 'powDifficulty' => __( 'Proof of Work Difficulty:', 'prosopo-procaptcha' ), - 'title' => __( 'Captcha Settings', 'prosopo-procaptcha' ), - 'type' => __( 'Type:', 'prosopo-procaptcha' ), - 'types' => array( - 'frictionless' => __( 'Frictionless', 'prosopo-procaptcha' ), - 'image' => __( 'Image', 'prosopo-procaptcha' ), - 'proofOfWork' => __( 'Proof of Work', 'prosopo-procaptcha' ), - ), - ), - 'domainLabels' => array( - 'title' => __( 'Whitelisted Domains', 'prosopo-procaptcha' ), - ), 'isDebugMode' => false, // todo move into settings as 'debug mode' option. 'secretKey' => $secret_key, 'siteKey' => $site_key,