Free tier: drop spurious BYO key gate; clarify bundled vs BYO
The previous free-tier commit (c0975fe) blocked USE_SERVER_KEY for
unlicensed users on the theory that this protected a "bundled key."
That conflated two different things:
• USE_SERVER_KEY = the user's OWN Gemini key, just stored server-side
via the StartOS configuration action (vs. browser localStorage).
Both paths are BYO — the user pays Google directly either way.
• Bundled key = a future relay where paid users' /api/process requests
are proxied through the operator's service and the operator absorbs
the API cost. Sketched in UPGRADE-DESIGN.md (deleted, in git history)
but NOT YET BUILT.
Blocking USE_SERVER_KEY broke a legitimate flow: a free user installs
the app on their own StartOS, sets their Gemini key via the config
action, then summarizes from the web UI without re-entering it.
This commit:
• Drops the BYO/USE_SERVER_KEY rejection in /api/process. Free users
can use a key from either path; the existing `if (!apiKey)` check
still catches the no-key-anywhere case with a helpful message.
• Reverts the frontend submit-button and handleSubmit checks to the
same key requirement for both tiers (state.apiKey OR state.hasServerKey).
• Drops "bundled API key" from the activation-screen subtitle and
"bring your own Gemini key" from the free-mode banner. Until the
relay is built, paid users still BYO too — promising otherwise in
upgrade copy is misleading.
• Keeps the parts that ARE legitimate free-vs-paid differentiators:
the one-at-a-time concurrency lock and skipping saveToHistory.
Also fixes the `make deploy` redundancy:
• bin/bump-version.sh accepts --from-deploy. When set, if there is no
.release-notes-pending.txt (consumed by a prior bump or never
written), exit 0 without prompting — the current version is already
fresh.
• Makefile passes --from-deploy from the deploy target. Standalone
`make bump` is unchanged (always prompts).
Result: `make bump` then `make deploy` no longer double-prompts. And
calling `make deploy` twice in a row (no new work) is idempotent on
the bump step.
This commit is contained in:
+15
-14
@@ -1324,21 +1324,24 @@
|
||||
// ── Process ──────────────────────────────────────────────────────────────
|
||||
|
||||
async function handleSubmit() {
|
||||
// Free tier requires BYO Gemini key — bundled key is licensed-only.
|
||||
const free = !isLicensed();
|
||||
const hasKey = free ? !!state.apiKey.trim() : (state.apiKey.trim() || state.hasServerKey);
|
||||
// Both tiers need a Gemini key — either entered in the web UI
|
||||
// (state.apiKey, localStorage) or set on the server via the StartOS
|
||||
// configuration action (state.hasServerKey). The free-vs-paid line
|
||||
// is concurrency + features, not key sourcing.
|
||||
const hasKey = state.apiKey.trim() || state.hasServerKey;
|
||||
if (!state.url.trim() || !hasKey) {
|
||||
if (free && !state.apiKey.trim() && state.url.trim()) {
|
||||
showToast("Free mode needs your own Gemini API key — open Settings to enter one.", "🔑");
|
||||
if (!hasKey && state.url.trim()) {
|
||||
showToast("Add your Gemini API key in Settings (or via the StartOS configuration action) to start summarizing.", "🔑");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const url = state.url.trim();
|
||||
|
||||
// If already processing — free tier blocks, paid tier queues.
|
||||
// If already processing — free tier blocks (one at a time),
|
||||
// paid tier queues for batch.
|
||||
if (state.loading) {
|
||||
if (free) {
|
||||
if (!isLicensed()) {
|
||||
showToast("Free mode handles one video at a time. Wait for the current one to finish.", "⏳");
|
||||
return;
|
||||
}
|
||||
@@ -1625,7 +1628,7 @@
|
||||
<p class="activation-sub">
|
||||
${loading
|
||||
? "Checking license…"
|
||||
: "Activate a Keysat license to unlock the full app — library, subscriptions, channel auto-queue, and the bundled API key. Or skip to use free mode (one video at a time, bring your own Gemini key)."
|
||||
: "Activate a Keysat license to unlock the full app — saved library, channel & podcast subscriptions, and auto-queue. Or skip to use free mode (one video at a time, no library)."
|
||||
}
|
||||
</p>
|
||||
${loading ? "" : `
|
||||
@@ -1681,7 +1684,7 @@
|
||||
">
|
||||
<span style="flex:1; min-width: 220px;">
|
||||
<strong style="color:#c4b5fd;">Free mode</strong>
|
||||
· one video at a time, bring your own Gemini key ·
|
||||
· one video at a time ·
|
||||
no library, no subscriptions
|
||||
</span>
|
||||
<a href="${escHtml(buyUrl)}" target="_blank" rel="noopener"
|
||||
@@ -1734,12 +1737,10 @@
|
||||
const __prevHistoryListEl = document.querySelector(".history-list");
|
||||
const __prevHistoryScroll = __prevHistoryListEl ? __prevHistoryListEl.scrollTop : 0;
|
||||
const free = !isLicensed();
|
||||
const submitNeedsBYO = free; // bundled key is licensed-only
|
||||
// Same key requirement for both tiers today — either web-UI key or
|
||||
// a server-side key set via the StartOS config action.
|
||||
const submitDisabled = !state.url.trim()
|
||||
|| (!isSubscribeUrl(state.url)
|
||||
&& (submitNeedsBYO
|
||||
? !state.apiKey.trim()
|
||||
: (!state.apiKey.trim() && !state.hasServerKey)));
|
||||
|| (!isSubscribeUrl(state.url) && !state.apiKey.trim() && !state.hasServerKey);
|
||||
app.innerHTML = `
|
||||
<!-- Top bar: title + action icons -->
|
||||
<div class="top-bar">
|
||||
|
||||
Reference in New Issue
Block a user