Add multi-tenant cloud mode: self-serve purchase, credit metering, core-decoupling

Introduces RECAP_MODE=multi alongside single-mode self-host:
- Tenant auth + accounts (magic-link via System SMTP), per-tenant credit pool,
  anonymous trial minting with per-IP/-64 caps
- Self-serve Pro/Max purchase: inline Lightning (BTCPay) + card (Zaprite),
  prepaid 30-day periods, expiry-reminder emails
- Core-decoupling: relay owns cloud tier/expiry keyed by Recaps user-id
- SQLite (better-sqlite3) schema for multi-mode; filesystem unchanged for single
- StartOS actions/versions through 0.2.155
This commit is contained in:
Keysat
2026-06-13 14:25:05 -05:00
parent db580abad7
commit 0ae59f3550
176 changed files with 23823 additions and 803 deletions
+13
View File
@@ -0,0 +1,13 @@
import { VersionInfo } from '@start9labs/start-sdk'
export const v_0_2_68 = VersionInfo.of({
version: '0.2.68:0',
releaseNotes: {
en_US:
'Two transcribe/analyze bugs surfaced by a 94-min YouTube run with gemini-3.1-flash-lite. (1) maxOutputTokens raised to 65,536 on Gemini transcribe calls. Default Gemini cap (~8,192) was silently truncating long-chunk transcripts mid-stream — observed a 45-min chunk that returned only 31:05 worth of speech (14 min missing) and another chunk that returned 2:05 of 45:00 (43 min missing). With the explicit limit, flash-lite has room to emit the full transcript; models with smaller native caps clamp internally. (2) Truncation detection: the chunk-transcribe loop now computes coverage = (last_entry_offset chunk_start) / chunk_duration. When coverage drops below 80% on chunks longer than a minute, a loud warning logs the missing-seconds count, the model name, and a suggestion to swap to a model with bigger output capacity or shrink chunk size. Coverage % also shown on the normal per-chunk completion log so the operator can spot near-misses. (3) Gap-handling in planAnalysisWindows. When TX produces a hole in the timeline (e.g., chunk 2 truncated → entries jump from 31:05 to 1:30:00), the old planner BROKE at the gap because the next entry sat past the window\'s end. Anything after the gap (a perfectly fine chunk 3 with full content) silently never got analyzed. New behavior: when a gap is detected, advance the body cursor forward to the next entry\'s body-stride boundary and keep planning windows instead of stopping. End result on the failing 94-min run: even if TX still truncates middle chunks (less likely after fix #1, but possible), the analyze pipeline will at least cover all entries that DID make it into the transcript instead of silently dropping the post-gap tail.',
},
migrations: {
up: async ({ effects }) => {},
down: async ({ effects }) => {},
},
})