diff --git a/docs/PROGRESS.md b/docs/PROGRESS.md index 510ca5b..5c2bc64 100644 --- a/docs/PROGRESS.md +++ b/docs/PROGRESS.md @@ -451,6 +451,16 @@ bodies total 37,095 bytes. **This retires the Option C frozen-tail invariant by existed only to police a boundary inside an unreviewable single line, and the append-only rule above supersedes it. No bespoke hash is needed for future updates: the diff is the proof. +### 2026-10-07 - Store path step a live and proven on production: the app marker gets the prerendered twins without the Google button or the Pricing link, the web gets its cached pages untouched, a web request right after an app request is a cache HIT of the web variant, and the eleven public pages are byte-identical for visitors + +**No row is edited. Outside this file: nothing in the repository; on production, the deploy of `bfd8c7b` (PR #239 merged by the owner's pinned line, Vercel success, Railway success). Rows 42, 69 and 81 are not touched, and Section 7 takes no deletions.** + +**THE READ, 2026-10-07 after the deploy (`curl`, read-only; an iPhone Safari user agent for the web, the same with `KnowFlowApp/1` appended for the app).** **The web variant:** `/en/login`, `/ar/login`, `/en/signup`, `/ar/signup` answer 200 with the Google button (`fill="#4285F4"` once each), `/en/privacy`, `/ar/privacy` and `/en` with two Pricing links, `/en/pricing` with its four and its Upgrade; every one `X-Nextjs-Prerender: 1`, `X-Vercel-Cache: HIT` or `PRERENDER`, `Cache-Control: public, max-age=0, must-revalidate`: the pages as they were, from the CDN. **The app variant:** the same six pages answer 200 with **no Google button and no Pricing link, in both locales**, also `X-Nextjs-Prerender: 1` and served from the cache (`PRERENDER` on first read, `HIT` on the second and third): the twin, prerendered at its own key; `/en` and `/en/pricing` answer **307 to `/en/dashboard`**. **No bleed:** a web request for `/en/login`, `/ar/login` and `/en/privacy` made immediately after the app request for the same URL answers the web variant (Google button and Pricing links present) as a cache `HIT`. **A web visit straight to `/en/native/login` answers 404** (`private, no-store`, the 404 page); the app's visit to it answers 200 from the cache. **Router prefetch:** `GET /en/login?_rsc=…` with `RSC: 1` and `Next-Router-Prefetch: 1` answers `text/x-component` for both; the web payload carries no platform prop, the app's carries `"platform":"native"` once, the provider of the twin's layout. **The API path:** `/api/check-limit` answers 401 to both, unauthenticated, as it must. **TTFB after, for the web:** `/en` 0.17 s, `/en/login` 0.19 s, `/en/privacy` 0.19 s, against 0.18–0.20 s before: unchanged, as the design promised. + +**WEB VISITORS SEE WHAT THEY SAW.** The eleven public pages captured from production before the change (`/`, `/login`, `/signup`, `/pricing` in both locales; `/about`, `/privacy`, `/forgot-password` in English) were fetched again after the deploy and compared with scripts, build-hashed asset paths and React's per-build comment markers removed: **all eleven identical**, once React's generated element ids (`_R_…_`, the `for`/`id` pairs of the form fields, which shift because the `[locale]` layout no longer renders the deleted `NativePlatformHeader` client component ahead of them) are masked; the pairs still match, and nothing a visitor sees or a crawler reads changed. + +**WHAT CLOSES AND WHAT DOES NOT.** Step a of `docs/store/STORE_PATH.md` is done: the marker is read per request, only removes, is gated in CI, and both variants are proven on production with no cache bleed. Step b is the Capacitor config and the native projects, exactly as the previous block fixed it. The one reading only the phone can take, client-side navigation inside the app between two rewritten pages and from a twin to the dashboard, is T5's first check. + ### 2026-10-07 - Store path step a built: the request-time platform marker; inside the app no purchase, upgrade or pricing surface and no Google button, read per request from `KnowFlowApp/` in the user agent; the web's pages stay on the CDN and the app is rewritten to prerendered twins; gated in CI by `verify-platform-gate.mjs` **No row is edited. Outside this file: `src/lib/platform.ts` (rewritten: `platformFromHeaders`, `purchaseLinksAllowed(platform)`, `googleSignInAllowed(platform)`, the build-time `PLATFORM` and `NEXT_PUBLIC_KF_PLATFORM` gone), `src/lib/platform-server.ts` (new, `currentPlatform()` over `headers()`, for the signed-in pages only), `src/components/platform/PlatformProvider.tsx` (new, context for client components), `src/components/platform/NativePlatformHeader.tsx` (deleted), `src/components/layout/SiteChrome.tsx` (new, the public site's chrome taken out of `(site)/layout.tsx` so two layouts can render it), `src/app/[locale]/native/` (new: `layout.tsx` with `robots: noindex` and `PlatformProvider platform="native"`, `(site)/layout.tsx` rendering the chrome without the Pricing link, and seven pages that are bare re-exports of `login`, `signup`, `about`, `contact`, `privacy`, `terms`, `refund`), `src/middleware.ts` (an app request for `/` or `//pricing` → 307 to the dashboard; for the seven pages above → rewrite to the twin; a web visit to a `/native/` path → the 404 page), `src/components/layout/SiteHeader.tsx` (`showPricing`), `src/app/[locale]/dashboard/layout.tsx`, `dashboard/page.tsx`, `dashboard/settings/page.tsx`, `dashboard/knowledge/new/page.tsx`, `src/lib/home-props.ts` (`buildHrefs(locale, platform)`, `appHrefs`), `src/components/auth/GoogleButton.tsx` (returns nothing inside the app), `src/app/[locale]/preview/student-home/page.tsx` (`?platform=native`), `scripts/verify-platform-gate.mjs` (new) as a step of the required `tsc` job, `scripts/verify-store-purchase-links.mjs` (the user-agent reading added), and `docs/store/STORE_PATH.md` (T1 done, T2's exact scope, corrections). No schema, grant, auth config, template or env change. Rows 42, 69 and 81 are not touched, and Section 7 takes no deletions.**