Lekture · internal · 17 September 2026

What we shipped vs the handover plan

Two open PRs close the QA blockers we found on device. Five of our fixes sit outside the handover matrix. The real gaps are the missing AI proxy (API #5), Android push config, iOS QA, and ops/legal — not admin auth or Apple ASN, which are already deployed.

2open PRs (mobile #5 → v4, API #5 → v3)
14handover items already on v4/v3
5fixes outside the matrix
6plan items still open (ops/QA/legal)

Verified in source

Handover items already landed on v4/v3

These came in with the earlier merges (mobile #3/#4, API #3). They are not in the two open PRs; verified by source inspection just now.

Landed verified by grep
ItemPlan IDEvidence
Unified VAD, level-scaled silence + mic sensitivity4.1 · 4.2getTurnDetection()/applyTurnDetection() present in WebRTCService.js on v4
Pause → Prompt → Praise ladder4.3Prompt ladder merged (digital-hardening)
Never read ahead4.4WebRTCService.js:332 “NEVER READ AHEAD” rule
Beginner leniency 70–80%6.4aLevel-driven scoring in textUtils.js
Age & grade passed to tutor6.4bprofileId sent on session create (ReadingPage:271, RealTimeMode:2047)
Backend read-ahead leak6.4copenai.service.ts no longer embeds passage; waits for app text
TypeORM synchronize off in prod6.2aNODE_ENV !== 'production' guard present on v3
PII out of API logs (COPPA)6.2bAuth/mail/report/purchase/session logs scrubbed
Trial 7 days / 150 pages6.3cSignup provisioning + mobile reads trialDaysRemaining/isTrial
Realtime voice retention off6.5a · 7.4tracing: null in openai.service.ts
Push registration stub (dummy token) removed—API rejects dummy-token-*
Remote push pipeline (FCM + APNs, config-gated)6.3a partialPipeline + /api/devices/* deployed; Android google-services.json still missing
Per-user admin auth: login + TOTP MFA, roles, invites, audit log6.2c donev3 admin module; deployed — /api/admin/auth/login, /setup-mfa, /verify-login, /accept-invite in the live prod Swagger
Apple App Store Server Notifications6.3b doneapple-asn.service.ts on v3; deployed — /api/subscriptions/apple/webhook live
Google Play RTDN webhookIAP done/api/subscriptions/google/webhook live

Open PRs

What the two open PRs change

Mobile #5 — feat/qa-hardening → v4

  • Mic permission requested before billing — ReadingPage + RealTimeMode now ask for RECORD_AUDIO (cross-platform via vision-camera) before the charge-bearing call. A denied mic no longer costs a page. found in QA outside plan
  • Backend-authoritative page billing — no local decrement before the session succeeds; balance re-synced from the API.
  • ReadingPage session lifecycle — single auto-start per mount, explicit Retry surface, whole-session metrics (readingSessionMetrics.js), illustration/credits UI. Supports the Digital Reader MVP.
  • IAP restore + Pricing rework — restore flow and plan screen fixes.
  • WebRTC metrics + log scrub — real AI-assist count, committed-chunk spoken-word totals (no phantom words), child-speech arrays kept out of logs (COPPA twin of 6.2b).
  • Push hardening — re-register device on persisted sessions, token-refresh identity guard, listener teardown (6.3a partial).
  • apiHandler 40s timeout — AbortController so a hung provider call can’t wedge the UI. outside plan
  • Android config — apply google-services plugin only when the JSON exists; placeholder release-keystore creds removed.
  • OCR unavailable handling — 404/503 now surfaces “scanning temporarily unavailable” instead of blaming the image. outside plan
  • EAS build pipeline — eas.json, project id, signed preview APK. outside plan

API #5 — feat/ai-ocr-proxy → v3

  • New server-side AI proxy — POST /ai/ocr (multipart image → {text, words}) and POST /ai/feedback. JWT-guarded, 30 req/min/user, JPEG/PNG + 4MB validation, prompts treat image text and assessment JSON as data (never instructions), store:false. Keeps the OpenAI key off the device. not a numbered matrix item
  • Additive module + 2 lines in app.module.ts; no migration.

State of play: built ≠ merged ≠ deployed

CodeBuilt (PR)MergedDeployed
Mobile QA hardening + mic fix (mobile #5)yesnono
AI proxy /ai/ocr + /ai/feedback (API #5)yesnono
Admin auth · Apple ASN · Google RTDN · device registeryesyesyes

Scope check

Fixes outside the handover plan

These were not in the August work package. They are real defects or tooling we added while getting a shippable build.

FixWhereWhy it mattered
Mic permission not requested before billingMobile #5Denied mic charged a page for a session that could never start
UI stuck after profile → PIN when a stray BACK firedNone (not a bug)Investigated and disproved; no change shipped
OCR/feedback proxy missing on prodAPI #5Scan & Read returned “No Text Detected” on a 404; now works once deployed
apiHandler had no timeoutMobile #5Hung provider calls locked the UI indefinitely
EAS/APK build pipelineMobile #5Needed a shareable signed APK; repo had no eas.json
Android google-services conditional + keystore creds removedMobile #5Build without Firebase config; no placeholder signing secrets in repo

Not done

Still open from the plan

The published handover page is stale on two of these: per-user admin auth (6.2c) and Apple ASN (6.3b) are implemented on v3 and deployed — verified against the live prod Swagger. What remains is ops/QA/legal, plus the AI proxy in API #5: built and tested locally, but unmerged and undeployed (prod still 404s /ai/ocr).

Blockers Owner / ops Legal
ItemPlan IDState
Real remote push delivery (Android native config)6.3aBlocked needs com.lekture google-services.json + APNs key; pipeline and /api/devices/* are live
Apple sign-in / Hide My Email + TestFlight child QA2.4 · 4.5Needs iOS QA code present on v4
Secret rotation / SSH lockout6.1Ops
Parental consent verification / legal review6.5b · 6.5cLegal
Google Play declarations6.5dOps
Scaling · model evaluation · owner/legal 7.x6.6 · 6.7 · 7.xFuture

Takeaway

Merge is safe; deploy is the real gate

Both PRs are clean and mergeable (mobile #5 → v4, API #5 → v3). The API change is additive; the mobile change is additive on top of the current v4 head.

Merging is not shipping. OCR/feedback only works after the API is deployed with OPEN_AI_KEY set on the droplet — prod still 404s /ai/ocr today. The app needs a rebuild/release from the merged branch; push, iOS/TestFlight and real store billing stay open.

Test suites added during hardening were removed from both PRs (17 Sep) — they are not part of the handover build. The app bundle is unaffected, so the existing signed preview APK still matches this code except for the dropped tests.

Method: PR file lists from GitHub, targeted git grep against upstream/v4 and upstream/v3, and on-device Android QA against prod and a local API. No iOS validation performed.