feat(radar): contributor + supporter claim buttons on the activation screen (#9710)

* feat(radar): add F4/T7 contributor-claim / supporter-plans link config

Pure, DB-free src/lib/radar/links.ts resolves the two outbound "get a
supporter key" URLs (contributor GitHub-OAuth claim + supporter plans
page), same env-override pattern as RADAR_FEED_URL. No pricing/value is
ever resolved here (D14) — only the link.

* feat(radar): relay F4/T7 claim/plans links via GET /api/radar/settings

Smallest-surface option per spec: no dedicated route. The existing
settings snapshot now also returns contributorClaimUrl/supporterPlansUrl
so the dashboard client never reads process.env itself. Both are plain
public URLs, gated by the same flag/auth checks as the rest of the
response.

* feat(radar): add contributor/supporter claim buttons to activation screen

F4/T7 — "I'm a contributor" opens the GitHub OAuth claim flow;
"Support the project" opens the plans/payment page. Both links come
from the settings fetch (never a hardcoded URL in this client
component) and open in a new tab. No price/value anywhere in the
copy — the destination page is the only place pricing lives (D14).

i18n: 5 new radarPage keys (claimSectionTitle, contributorButton,
contributorHint, supporterButton, supporterHint) added to all 43
locale files with the English copy as fallback value.

* docs(radar): document F4/T7 supporter-key acquisition paths

RADAR.md: new "Getting a supporter key" section covering both claim
flows, the two env-var overrides, and the current gap (no dedicated
key-paste input in the dashboard yet — POST /api/radar/settings is the
only way to set one today). ENVIRONMENT.md + .env.example: register
RADAR_CONTRIBUTOR_CLAIM_URL / RADAR_SUPPORTER_PLANS_URL for
check:env-doc-sync.

---------

Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
This commit is contained in:
Diego Rodrigues de Sa e Souza
2026-08-07 16:41:00 -03:00
committed by GitHub
parent 976d670ff3
commit 02534f4e8e
52 changed files with 574 additions and 11 deletions

View File

@@ -3,6 +3,13 @@
* snapshot. Powers the dashboard page's "am I already opted in?" check so
* a reload doesn't re-show the activation screen (see FIX 3).
*
* Also relays the two F4/T7 "get a supporter key" outbound links
* (`contributorClaimUrl`, `supporterPlansUrl` — see `@/lib/radar/links`) so
* the client component never reads `process.env` itself. Smallest surface
* per spec: no dedicated route, reuses this one. Both are plain public
* URLs (no secret, no pricing) — safe to expose alongside the settings
* snapshot, gated by the same flag/auth checks below.
*
* POST /api/radar/settings — set Radar opt-in and/or supporter key.
*
* Zod-validated body: { optIn?: boolean, supporterKey?: string|null }
@@ -22,6 +29,7 @@ import { CORS_HEADERS, handleCorsOptions } from "@/shared/utils/cors";
import { isFeatureFlagEnabled } from "@/shared/utils/featureFlags";
import { isAuthenticated } from "@/shared/utils/apiAuth";
import { setRadarOptIn, setRadarKey, getRadarSettings } from "@/lib/db/radar";
import { getContributorClaimUrl, getSupporterPlansUrl } from "@/lib/radar/links";
import { buildErrorBody } from "@omniroute/open-sse/utils/error";
export const dynamic = "force-dynamic";
@@ -75,6 +83,8 @@ export async function GET(request: Request) {
optIn: settings.optIn,
hasSupporterKey: settings.supporterKey !== null,
supporterKeyMasked: maskKey(settings.supporterKey),
contributorClaimUrl: getContributorClaimUrl(),
supporterPlansUrl: getSupporterPlansUrl(),
},
{ headers: { ...CORS_HEADERS, "Cache-Control": "no-store" } },
);