Legal pages: privacy policy + EULA at /privacy/ and /eula/ #253

Merged
developer merged 7 commits from feature/legal-pages into development 2026-07-13 11:55:45 +00:00
Owner

Hosts the privacy policy (/privacy/) and the EULA (/eula/) as static pages via the render sidecar, and links them from the landing footer alongside the existing offer + feedback. First slice of the documents track for the Android/RuStore release (RuStore needs a hosted privacy-policy URL).

What

  • New ui/legal/privacy_ru.md + ui/legal/eula_ru.md, reworked from the source documents.
  • renderLegalHtml generalised out of renderOfferHtml; new renderer routes GET /privacy/ + GET /eula/ (static, no backend fetch; 301 from the slashless form); markdown baked into the image.
  • Edge: @legal caddy matcher now covers /offer/ + /privacy/ + /eula/; CI probes assert each page's canonical URL + the seller INN (so a missing route can't fall through to the landing).
  • Footer: Пользовательское соглашение | Политика конфиденциальности | Публичная оферта | Обратная связь.
  • Docs baked: ARCHITECTURE, FUNCTIONAL(+_ru), renderer/README. Tests: renderer legal.test.mjs, ui renderLegalHtml unit, landing footer e2e.

Decisions applied (from our interview)

  • Seller INN unified to 290210610742 (the value the offer + CI already use).
  • Data collection kept but scoped: passport/payment/ID data only on voluntary provision (support / identity check), not routine collection.
  • EULA governing law leads with Russian law + RF jurisdiction; France/England&Wales retained as residence tiers.
  • The 'only the English version is legally binding' clause removed entirely.
  • 'КОМПАНИЯ' → 'Компания' (no shout-case).

Please review

  • The legal wording of both documents.
  • Specifically the EULA governing-law section: I'm not a lawyer — I phrased it as residence tiers (RF primary) to avoid a two-law contradiction; confirm that reads right.

Not in this PR

  • EN versions + the language switcher (next slice).
  • Offer language switcher + EN offer (later slice).

Contour-safe: no schema/wire change; pure content + a static render route + an edge matcher + docs.

Hosts the privacy policy (`/privacy/`) and the EULA (`/eula/`) as static pages via the render sidecar, and links them from the landing footer alongside the existing offer + feedback. First slice of the documents track for the Android/RuStore release (RuStore needs a hosted privacy-policy URL). ## What - New `ui/legal/privacy_ru.md` + `ui/legal/eula_ru.md`, reworked from the source documents. - `renderLegalHtml` generalised out of `renderOfferHtml`; new `renderer` routes `GET /privacy/` + `GET /eula/` (static, no backend fetch; 301 from the slashless form); markdown baked into the image. - Edge: `@legal` caddy matcher now covers /offer/ + /privacy/ + /eula/; CI probes assert each page's canonical URL + the seller INN (so a missing route can't fall through to the landing). - Footer: Пользовательское соглашение | Политика конфиденциальности | Публичная оферта | Обратная связь. - Docs baked: ARCHITECTURE, FUNCTIONAL(+_ru), renderer/README. Tests: renderer legal.test.mjs, ui renderLegalHtml unit, landing footer e2e. ## Decisions applied (from our interview) - Seller INN unified to 290210610742 (the value the offer + CI already use). - Data collection kept but scoped: passport/payment/ID data only on voluntary provision (support / identity check), not routine collection. - EULA governing law leads with Russian law + RF jurisdiction; France/England&Wales retained as residence tiers. - The 'only the English version is legally binding' clause removed entirely. - 'КОМПАНИЯ' → 'Компания' (no shout-case). ## Please review - The legal wording of both documents. - Specifically the EULA governing-law section: I'm not a lawyer — I phrased it as residence tiers (RF primary) to avoid a two-law contradiction; confirm that reads right. ## Not in this PR - EN versions + the language switcher (next slice). - Offer language switcher + EN offer (later slice). Contour-safe: no schema/wire change; pure content + a static render route + an edge matcher + docs.
developer added 1 commit 2026-07-13 10:09:35 +00:00
feat(legal): host the privacy policy and EULA at /privacy/ and /eula/
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 11s
CI / integration (pull_request) Successful in 22s
CI / ui (pull_request) Successful in 1m14s
CI / conformance (pull_request) Successful in 10s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Failing after 40s
0f3b4dbcff
Author ui/legal/{privacy,eula}_ru.md, reworked from the source documents: the seller INN is unified (290210610742), contacts unified to the Telegram bot + email + postal address, the EULA governing-law clause leads with Russian law + jurisdiction as residence tiers, the single-binding-language clause is dropped, data collection is scoped to voluntary/support provision, and "Компания" is no longer shout-cased.

Serve both as static pages through the render sidecar, reusing a shared renderLegalHtml generalised from renderOfferHtml: new GET /privacy/ and GET /eula/ (301 from the slashless form), the markdown baked into the image, no backend fetch. Route them at the edge via the @legal caddy matcher with a CI probe asserting each page's canonical URL + the seller INN, so a missing route cannot silently fall through to the landing. Add the two links to the landing footer.

Docs baked in: ARCHITECTURE (renderer legal pages + edge routing), FUNCTIONAL (+_ru) footer, renderer/README routes. Tests: renderer legal.test.mjs, ui renderLegalHtml unit, landing footer e2e.
developer added 1 commit 2026-07-13 10:25:32 +00:00
fix(ci): retry the /privacy/ and /eula/ contour probe with a timeout
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 11s
CI / integration (pull_request) Successful in 23s
CI / ui (pull_request) Successful in 1m14s
CI / conformance (pull_request) Successful in 10s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Failing after 2m31s
807edff327
The single-shot probe raced the render sidecar during the rolling deploy: across two attempts a different route flaked each time (/privacy/, then /eula/) against an otherwise-healthy renderer, while the contour served all three pages correctly — a deploy-time transient (a slow first render of the large EULA while every container recreates, or a connection blip). Wrap the check in the same 20x3s retry the landing/gateway/backend probe uses, with a 10s per-attempt wget timeout, so it waits the transient out instead of failing the deploy.
developer added 1 commit 2026-07-13 10:36:34 +00:00
fix(renderer): pre-render the static legal pages at boot
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 11s
CI / integration (pull_request) Successful in 19s
CI / ui (pull_request) Successful in 1m13s
CI / conformance (pull_request) Successful in 11s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Failing after 2m28s
5a4c460268
Serving /eula/ re-parsed the large (~122 KB) EULA markdown on every request. Under the rolling deploy's host contention (the renderer is capped at 1 CPU / 192 MB) that was slow enough that the contour /eula/ probe failed for its whole 60s retry window, while the smaller /privacy/ squeaked through; both serve fine once the host is idle. Render privacy + eula once at boot and serve the cached HTML (now ~1.5 ms, a memcpy). The offer stays per-request for its live price splice; the probe retry stays as a readiness backstop.
developer added 1 commit 2026-07-13 10:45:39 +00:00
fix(ci): make the legal-page probe size-independent
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 11s
CI / integration (pull_request) Successful in 21s
CI / ui (pull_request) Successful in 1m13s
CI / conformance (pull_request) Successful in 10s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m56s
1d77ee83b3
The /eula/ probe fetched the full ~129 KB page. While the monitoring stack boots after the rolling deploy and the CPU-capped (1 CPU / 192 MB) renderer is starved, that transfer exceeded the wget timeout for the entire 60s retry window, while the 3x-smaller /privacy/ passed — pre-rendering the pages did not help because the bottleneck is the transfer, not the render. Fetch only the <head> (head -c 4096) and assert the page's canonical URL, which uniquely identifies the rendered legal doc reaching the edge (the landing's canonical is erudit-game.ru/); the check now transfers ~4 KB regardless of page size.
developer added 1 commit 2026-07-13 11:00:42 +00:00
fix(legal): wrap the privacy table's first column, top-align cells
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 11s
CI / integration (pull_request) Successful in 21s
CI / ui (pull_request) Successful in 1m13s
CI / conformance (pull_request) Successful in 11s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m54s
7df078f5ed
The shared legal-page template inherited the offer's shrink-to-fit product-name column (width:1% + white-space:nowrap), which stopped the privacy data table's long prose first column from wrapping and blew the table out horizontally. Scope that rule to the offer (body.offer) and top-align all legal-table cells for the multi-line privacy rows.
developer added 1 commit 2026-07-13 11:22:58 +00:00
feat(legal): bilingual (RU + EN) legal pages with a language + theme switcher
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 10s
CI / integration (pull_request) Successful in 21s
CI / ui (pull_request) Successful in 1m14s
CI / conformance (pull_request) Successful in 10s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m48s
de5ab9186c
Add English versions of the privacy policy, EULA and offer (ui/legal/*_en.md) and render each legal page as one self-contained bilingual document: both language bodies plus a header language toggle and theme toggle (no back), a small inline ES5 script that switches language client-side (no reload, default Russian + persisted) and applies the theme (system default + persisted override) — mirroring the landing. The offer's English view transliterates the Russian product names spliced from the live catalog.

renderLegalHtml now takes both language sources; renderOffer splices the price list into both; the renderer bakes and reads the _en sources and pre-renders the static pages at boot. Also wrap the /offer/ contour probe in the same retry+timeout as the legal probe (the offer page is now bilingual and larger). Docs + renderer/ui tests updated.
developer added 1 commit 2026-07-13 11:49:02 +00:00
fix(legal): translate the offer price-list headings in the English view
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 11s
CI / integration (pull_request) Successful in 20s
CI / ui (pull_request) Successful in 1m14s
CI / conformance (pull_request) Successful in 10s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m54s
25b5ed5516
The price list is spliced in Russian; the client-side offer transliteration turned its section headings and column headers into transliteration too. Translate the known backend-projected strings (the two section headings and the column headers Наименование/Рубли/Голоса в VK/Stars в Telegram/«Фишки») to English and transliterate only the product names, as requested.
owner approved these changes 2026-07-13 11:55:03 +00:00
developer merged commit 8becdb45e4 into development 2026-07-13 11:55:45 +00:00
developer deleted branch feature/legal-pages 2026-07-13 11:55:45 +00:00
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: developer/scrabble-game#253