Skip to content

chore(content): declare the field that titles each model's entries - #191

Merged
ABB65 merged 1 commit into
mainfrom
chore/title-field-migration
Aug 13, 2026
Merged

chore(content): declare the field that titles each model's entries#191
ABB65 merged 1 commit into
mainfrom
chore/title-field-migration

Conversation

@ABB65

@ABB65 ABB65 commented Aug 13, 2026

Copy link
Copy Markdown
Member

@contentrain/types@1.0.0 makes ModelDefinition.title_field required. This is the migration of Studio's own .contentrain/, so the bump (T07b) has something valid to land on — without it, a bumped Studio fails validation on its own dictionary.

Produced by contentrain@0.9.2 validate --fix, not by hand. The point of the tool is that the choice and the rule behind it are the CLI's; a hand-written title_field would be exactly the guess this feature replaces.

What it chose

model kind title_field
agent-messages, agent-prompts, error-messages, ui-strings dictionary key — the only legal value
email-templates collection name — over slug and subject
plan-features, plans, starters collection name
auth-marketing singleton headline

Errors go 10 → 1.

The one error left is a false positive

[ERROR] plan-features → key → cdn-api-keys: Potential secret detected in value

The plan feature whose id is cdn-api-keys has key: "cdn.api_keys" — a feature name, not a credential. Worth reporting upstream now that contentrain validate exits non-zero: a CI step running it would fail forever on a correctly-named feature flag, and the only workaround is renaming the feature.

Carried along, because the same command writes them

  • Canonical key order in model files, from MODEL_FIELD_ORDER moving into @contentrain/types. plans.json had its top-level keys scrambled (description first, id/kind/name at the bottom); fields now sort alphabetically.
  • Two error-messages keys swap into order.
  • Orphan meta records for plans/community and nine plan features. They land as source: import, status: draft — the same shape every neighbouring record already has, so nothing changes what the app renders. I checked that before accepting it: status is already draft on every existing plan record, so nothing is being newly hidden.
  • context.json regenerates.

Why it was run in an isolated copy

--fix works through the contentrain branch, and this repo's contentrain is 44 commits behind main. The CLI refused rather than writing onto stale content:

Cannot fast-forward "chore/title-field-migration" to contentrain tip.
The base branch has diverged.

That is the right refusal, and it points at something separate worth knowing: Studio's own dictionary is maintained on main by PR, so the contentrain branch here is vestigial — which also means Studio's chat agent editing Studio's own dictionary would write somewhere the app never reads. Out of scope here; flagging it.

So the fix was produced in a throwaway copy of .contentrain/ on its own contentrain branch, and the resulting files were brought over and re-validated in place.

Verified

  • contentrain@0.9.2 validate --root . — 10 errors → 1 (the false positive above)
  • npx contentrain-query generate — 9 models, 12 files, clean
  • pnpm lint — 0 errors (7 pre-existing warnings)
  • pnpm typecheck — clean
  • pnpm test — 141 files / 1196 tests

Next

T07b: bump @contentrain/types 1.0.2 / @contentrain/mcp 3.0.2 / @contentrain/query 7.0.4, consume title_field in the entry-title resolution, and add the selector. That unblocks T05 → T08b → T06.

Customer projects still need this same migration before they can be written to by a bumped Studio — Lanista/collabers included. That is a live-repo operation and is not part of this PR.

`@contentrain/types@1.0.0` makes `ModelDefinition.title_field` required.
Every consumer used to guess which field was an entry's title, and the
guess was wrong in ways that made listings unreadable — a hero slide
titled by a relation ID, an article titled by its slug.

This is the migration, so the bump has something valid to land on. It
has to come first: without it, a bumped Studio would fail validation on
its own dictionary.

Produced by `contentrain@0.9.2 validate --fix`, not by hand — the point
of the tool is that the choice and the rule behind it are the CLI's, and
a hand-written `title_field` would be exactly the guess this replaces.

    4 dictionaries  → key       (the entry key is the title; the only legal value)
    3 collections   → name      over slug / subject / description
    1 singleton     → headline
    1 collection    → name      (starters)

Errors go 10 → 1. The one left is a false positive: the plan feature
whose id is `cdn-api-keys` has `key: "cdn.api_keys"`, and the secret
detector reads the name as a credential. Worth reporting upstream now
that `contentrain validate` exits non-zero — a CI step running it would
fail on a correctly-named feature flag.

Carried along, because the same command writes them:

- model files pick up canonical key order from `MODEL_FIELD_ORDER`,
  which moved into `@contentrain/types`. `plans.json` had its top-level
  keys scrambled; fields sort alphabetically now.
- two `error-messages` keys swap into canonical order.
- orphan meta records for `plans/community` and nine plan features.
  They land as `source: import`, `status: draft` — the same shape every
  neighbouring record already has, so nothing changes what the app
  renders.
- `context.json` regenerates.

Run in an isolated copy rather than here: `--fix` works through the
`contentrain` branch, and this repo's is 44 commits behind `main` — the
CLI refused rather than writing onto stale content, which is the right
refusal and a separate thing to fix. Studio's own dictionary lives on
`main` and is edited by PR; the resulting files were brought over and
re-validated in place.
@ABB65
ABB65 merged commit 1b07d11 into main Aug 13, 2026
2 checks passed
@ABB65
ABB65 deleted the chore/title-field-migration branch August 13, 2026 21: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