chore(release): v0.4.13 (versionCode 40) — waitlist retry queue (#166)

* chore(release): v0.4.13 (versionCode 40) — waitlist retry queue reaches users

Ships 2f81d34 (#165): failed waitlist signups are persisted on-device and
retried on app foreground instead of silently falling back to mailto.
Until this Play release, no user is running that fix.

Co-Authored-By: Paperclip <noreply@paperclip.ing>

* fix(waitlist): stamp the app version into the mailto escape hatch

AGE-100 asks for the post-release mailto count "split by app version where the
mail body allows it". It did not allow it: the body was "Sign me up!\n\nEmail: x"
and nothing else, so a mail from an unreachable pre-v0.4.8 sideload is byte-identical
to one from a current build whose retry queue leaked. Those two readings have
opposite meanings — the first is the known permanent cohort, the second is a defect.

Now the escape hatch appends "App: OpenCode Mobile v<version>" (app.json, same
source Sentry uses). Absence of the line == pre-v0.4.13 build. waitlist.ts stays
free of react-native/JSON imports; the screen injects the version.

Co-Authored-By: Paperclip <noreply@paperclip.ing>

---------

Co-authored-by: engineer <engineer@macbookpro.lan>
Co-authored-by: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Den
2026-08-14 02:02:53 -07:00
committed by GitHub
parent 2f81d34200
commit af7da46c0f
10 changed files with 67 additions and 10 deletions

View File

@@ -49,6 +49,21 @@ test("mailto escape hatch works without an email", () => {
assert.ok(!url.includes("Email"))
})
// AGE-100: the reconciler has to be able to say which build produced a mailto
// signup. Pre-v0.4.8 sideloads (no signup API, unreachable by any release)
// send no App: line; a current build sending one means the retry queue leaked
// and that is a new defect, not the known stale cohort.
test("mailto escape hatch stamps the app version when given one", () => {
const url = buildWaitlistMailtoUrl("dev@example.com", "0.4.13")
assert.ok(url.includes(encodeURIComponent("App: OpenCode Mobile v0.4.13")))
assert.ok(url.includes(encodeURIComponent("Email: dev@example.com")))
})
test("mailto escape hatch omits the version line when the version is unknown", () => {
const url = buildWaitlistMailtoUrl("dev@example.com")
assert.ok(!url.includes("App%3A"))
})
// --- retry decision ---
// 502 named explicitly: the server returns it when Brevo itself fails, and the

View File

@@ -36,10 +36,20 @@ export function buildWaitlistPayload(email: string): { email: string; source: st
* automatically: a failed signup is queued locally and retried
* (waitlist-queue.ts). This URL is only offered after retries keep failing,
* behind an explicit "still not working? email us" tap.
*
* `appVersion` stamps the build into the mail body (AGE-100). Without it the
* hourly reconciler that heals these mails
* (VibeBrowserProductPage/scripts/reconcile-waitlist-mailto.js) cannot tell a
* ~436-device pre-v0.4.8 sideload — which has no signup API at all and can
* never be fixed by shipping code — from a current build that still fell back,
* which would be a live defect. Absence of the line means "pre-v0.4.13 build".
*/
export function buildWaitlistMailtoUrl(email: string): string {
export function buildWaitlistMailtoUrl(email: string, appVersion?: string): string {
const subject = encodeURIComponent("OpenCode Connect Waitlist")
const body = encodeURIComponent(email ? `Sign me up!\n\nEmail: ${email}` : "Sign me up!")
const lines = ["Sign me up!"]
if (email) lines.push("", `Email: ${email}`)
if (appVersion) lines.push("", `App: OpenCode Mobile v${appVersion}`)
const body = encodeURIComponent(lines.join("\n"))
return `mailto:${WAITLIST_FALLBACK_EMAIL}?subject=${subject}&body=${body}`
}