refactor(settings): remove the preview-feature opt-ins

The per-account preview switch was kept for the topic overview pages,
which were dropped before they shipped. Its one flag was stored, served
and backed up, and read by nothing; the column-reader audit listed it as
a pending consumer that will not come.

Removed completely:

- `/api/settings/preview-features` (GET, PATCH) is retired: it answers
  410 Gone with `meta.errorCode: route.retired` and `removedIn: 1.46.0`,
  and the contract publishes it under Retired. The route, its validation
  schema, the `PreviewFeatures` OpenAPI schemas and the settings module
  are deleted.
- Migration 0485 drops `users.preview_features_json` under a bounded lock
  wait, with the retry marker.
- The backup no longer writes the field. A file from v1.44 or v1.45 that
  carries it still restores: the schema accepts it and no codec reads it,
  so nothing is refused or written for it. The backup-parity goldens
  lose the field and apply one setting fewer.
- The data-wipe plan entry and the sharing-surface actor entry go with
  the route (frozen count 273 -> 272).

No client build reads the route: neither iOS repository nor any local
checkout references it.
This commit is contained in:
Marc-André Bombeck committed 2026-10-25 00:44:15 +02:00
1 parent f3b9329fb2
commit 2ae23f4ca8
26 files changed
+125 -437

No files matched your search

+4 -3
View File
@@ -2163,8 +2163,6 @@ const ACTOR_ROUTES: Record<string, string> = {
"The UI language belongs to the person reading the screen, never to the record on it. Under a record scope this would transplant a delegate's choice onto the owner's row and send the owner's cron mail in a language they may not read. It has to keep working rather than merely refuse safely: the switcher's mount-time backfill fires on every page load, including the shared dashboard.",
"app/api/settings/module-list-layout/route.ts":
"How the person's own labs, illness and checkups lists are laid out: card or list view, manual order, sort. It reads and writes the caller's own row only. Inside another record the ids of a saved order simply match nothing and the list keeps the server order, so serving the person's own choice there reveals nothing of the owner's and grants nothing; refusing it under a switch broke the list controls in exactly the context they are used in.",
"app/api/settings/preview-features/route.ts":
"The person's own opt-in to preview features. A preview entry is chrome of the person reading the screen, never a property of the record on it; it reads and writes the caller's own row and nothing of the owner's.",
"app/api/feature-flags/route.ts":
"Reads the `AppSettings` singleton and no user row at all, so there is no record for a switch to substitute. It answers about the deployment, which for this purpose is the caller's side of the request; the shell gates the Coach launcher and the assistant surfaces on it, so a 403 here is a piece of chrome deciding it does not exist.",
};
@@ -2273,8 +2271,11 @@ const ACTOR_ROUTES: Record<string, string> = {
* side). The activity goals route does not: setting or changing goals stays
* owner-only, and a delegate sees the goals only as the calendar reports them.
* 270 -> 273.
*
* v1.46 -- the preview-feature switch is removed with its column; the topic
* pages it was kept for were dropped. 273 -> 272.
*/
const FROZEN_ENTRY_COUNT = 273;
const FROZEN_ENTRY_COUNT = 272;
/**
* The two surfaces that authenticate a Bearer token outside `requireAuth` —