Skip to content

PR-i18n-1b: remove fm_lang cookie (privacy-policy reconciliation)#19

Merged
MrChengLen merged 1 commit into
mainfrom
pr-i18n-1b-remove-cookie
May 7, 2026
Merged

PR-i18n-1b: remove fm_lang cookie (privacy-policy reconciliation)#19
MrChengLen merged 1 commit into
mainfrom
pr-i18n-1b-remove-cookie

Conversation

@MrChengLen

Copy link
Copy Markdown
Owner

PR-i18n-1 introduced an fm_lang cookie as sticky locale preference. The published privacy policy (app/templates/privacy.html §6) commits to "FileMorph sets no cookies on its own domain" — verifying the rest of the codebase confirmed the project is otherwise 100% cookie-free (JWT auth lives in localStorage). The new cookie therefore turned the privacy promise into a falsehood.

Resolution: drop the cookie. URL is the single source of truth for locale; the in-nav switcher already navigates to prefixed URLs, so a user who picks EN stays on EN as long as in-app links propagate current_prefix. Returning visitors to unprefixed URLs fall through to Accept-Language and the operator default. Logged-in sticky preference will land server-side via User.preferred_lang in PR-i18n-3 — strictly better than a cookie because it survives device changes.

Changes:

  • app/core/i18n.py: drop COOKIE_NAME / COOKIE_MAX_AGE constants and is_explicit_locale_signal helper; resolution chain shrinks from 5 to 4 steps (URL-prefix → query-param → Accept-Language → default).
  • app/main.py: drop set_cookie block in locale_resolver middleware; middleware still caches the resolved locale on request.state.locale.
  • tests/test_i18n.py: drop 5 cookie-specific tests; add parametrized regression-guard test_no_locale_cookie_set_on_any_route covering /, /de/, /en/, /?lang=de|en, /login, /de/login, /en/login.

In-flight cookies on existing browsers expire naturally via Max-Age (~30 days); server simply ignores them in the meantime.

461 tests passing (+3 vs main: parametrized guard cases).

PR-i18n-1 introduced an `fm_lang` cookie as sticky locale preference.
The published privacy policy (`app/templates/privacy.html` §6) commits
to "FileMorph sets no cookies on its own domain" — verifying the rest
of the codebase confirmed the project is otherwise 100% cookie-free
(JWT auth lives in localStorage). The new cookie therefore turned the
privacy promise into a falsehood.

Resolution: drop the cookie. URL is the single source of truth for
locale; the in-nav switcher already navigates to prefixed URLs, so a
user who picks EN stays on EN as long as in-app links propagate
`current_prefix`. Returning visitors to unprefixed URLs fall through to
Accept-Language and the operator default. Logged-in sticky preference
will land server-side via `User.preferred_lang` in PR-i18n-3 — strictly
better than a cookie because it survives device changes.

Changes:
- `app/core/i18n.py`: drop COOKIE_NAME / COOKIE_MAX_AGE constants and
  `is_explicit_locale_signal` helper; resolution chain shrinks from 5
  to 4 steps (URL-prefix → query-param → Accept-Language → default).
- `app/main.py`: drop `set_cookie` block in `locale_resolver`
  middleware; middleware still caches the resolved locale on
  `request.state.locale`.
- `tests/test_i18n.py`: drop 5 cookie-specific tests; add parametrized
  regression-guard `test_no_locale_cookie_set_on_any_route` covering
  /, /de/, /en/, /?lang=de|en, /login, /de/login, /en/login.

In-flight cookies on existing browsers expire naturally via Max-Age
(~30 days); server simply ignores them in the meantime.

461 tests passing (+3 vs main: parametrized guard cases).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@MrChengLen MrChengLen merged commit 57e3bf1 into main May 7, 2026
4 checks passed
@MrChengLen MrChengLen deleted the pr-i18n-1b-remove-cookie branch May 25, 2026 07:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant