Split out of #258, which fixes the one row rather than the mechanism.
tags is Option<Vec<String>> on AdminCreateAppRequest and is simply skipped when absent (lnvps_api_admin/src/admin/apps.rs:286-317): no validation runs, and nothing warns. An app created without it is enabled, orderable and absent from ?tag= results and from every app_count in GET /api/v1/app-tags. That is exactly how buzz-relay reached production untagged, and the same call would do it again tomorrow.
category had the same failure mode and was made NOT NULL for it (lnvps_db/migrations/20260726110000_app_seo_metadata.sql:9-12) — a nullable value that renders correct-but-empty and errors nowhere.
Options, in the order I would pick them:
- Require at least one tag on create. Breaking for any admin client that omits the field today, which as far as I can see is only our own tooling — worth confirming before it ships.
- Warn on create/update when the resulting tag set is empty, in the response body. Not breaking, and no stronger than the thing it replaces: nobody reads it.
- Leave it and catch untagged apps in a report. Cheapest, and the failure stays silent between runs.
I lean on 1. A tag set is not editorial polish — it is how the front end finds the product at all, and the cost of getting it wrong is an app customers cannot see.
Not urgent: the catalog gains a row every few weeks and #258 clears the current one.
Split out of #258, which fixes the one row rather than the mechanism.
tagsisOption<Vec<String>>onAdminCreateAppRequestand is simply skipped when absent (lnvps_api_admin/src/admin/apps.rs:286-317): no validation runs, and nothing warns. An app created without it is enabled, orderable and absent from?tag=results and from everyapp_countinGET /api/v1/app-tags. That is exactly howbuzz-relayreached production untagged, and the same call would do it again tomorrow.categoryhad the same failure mode and was madeNOT NULLfor it (lnvps_db/migrations/20260726110000_app_seo_metadata.sql:9-12) — a nullable value that renders correct-but-empty and errors nowhere.Options, in the order I would pick them:
I lean on 1. A tag set is not editorial polish — it is how the front end finds the product at all, and the cost of getting it wrong is an app customers cannot see.
Not urgent: the catalog gains a row every few weeks and #258 clears the current one.