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

+1 -69
View File
@@ -27,10 +27,7 @@ import {
MODULE_LIST_VIEWS,
MODULE_SORT_DIRS,
} from "@/lib/settings/module-list-layout";
import {
moduleListLayoutPutSchema,
previewFeaturesPatchSchema,
} from "@/lib/validations/settings-prefs";
import { moduleListLayoutPutSchema } from "@/lib/validations/settings-prefs";
const moduleListPrefsEntry = z
.object({
@@ -72,20 +69,6 @@ const moduleListLayoutSchema = z
"Per-user presentation of the labs, illness and checkups lists. Display-only; a client that does not render a list ignores it.",
});
const previewFeaturesSchema = z
.object({
topics: z
.boolean()
.describe(
"Topic overview pages above the single-metric Insights pages. Off by default.",
),
})
.meta({
id: "PreviewFeatures",
description:
"Per-user opt-in to preview features, one boolean per flag, every flag off by default.",
});
// v1.16.11 — the one threshold read every dose-status consumer makes
// (cards, table, take-all-due derivation). `lateMinutes` /
// `missedMinutes` are the operator-level singleton; the low-stock
@@ -970,57 +953,6 @@ export const settingsPaths: NonNullable<ZodOpenApiObject["paths"]> = {
},
},
},
"/api/settings/preview-features": {
get: {
tags: ["Meta"],
summary: "Get the preview-feature opt-ins",
description: "Every flag, off unless the caller switched it on.",
responses: {
"200": {
description: "The opt-ins.",
content: {
"application/json": {
schema: dataEnvelope(
previewFeaturesSchema,
"PreviewFeaturesEnvelope",
),
},
},
},
...stdResponses,
},
},
patch: {
tags: ["Meta"],
summary: "Switch preview features on or off",
description:
"Sets the flags the body names and keeps the rest. An unknown flag or an empty body is refused with 422.",
requestBody: {
required: true,
content: {
"application/json": {
schema: previewFeaturesPatchSchema.meta({
id: "PreviewFeaturesPatchBody",
}),
},
},
},
responses: {
"200": {
description: "The opt-ins as stored.",
content: {
"application/json": {
schema: dataEnvelope(
previewFeaturesSchema,
"PreviewFeaturesSavedEnvelope",
),
},
},
},
...stdResponses,
},
},
},
"/api/settings/privacy-summary": {
get: {
tags: ["Meta"],