Skip to content

fix(cdn): honor default locale, locale_strategy, and singleton status in builds#152

Merged
ABB65 merged 1 commit into
mainfrom
fix/cdn-non-i18n-locale-and-status-filter
Jul 15, 2026
Merged

fix(cdn): honor default locale, locale_strategy, and singleton status in builds#152
ABB65 merged 1 commit into
mainfrom
fix/cdn-non-i18n-locale-and-status-filter

Conversation

@ABB65

@ABB65 ABB65 commented Jul 15, 2026

Copy link
Copy Markdown
Member

Problem

A connected project reported published non-i18n content (sponsors) serving 200 {} from the CDN. Root cause was not the reporter's guess — three related bugs in the CDN build path, all from path/meta resolution diverging from MCP's canonical contract.

Fixes

1. Non-i18n meta resolved under supported[0] instead of the default locale

Non-i18n content/meta lives under the default locale (where MCP writes it), which is not necessarily supported[0]. The builder used locales[0], so a project whose default differs from supported[0] (e.g. default=tr, supported=[en,tr]) read a non-existent meta file — the status filter went blind (drafts leaked, meta output empty). Now uses config.locales.default, mirroring brain-cache.ts. Fixed for collections, singletons/dictionaries, and non-i18n documents.

2. resolveContentPath ignored locale_strategy

It only resolved the default file layout. suffix/directory/none i18n models read the wrong path → silent skip in the CDN build and brain cache. Realigned byte-for-byte with MCP's contentFilePath/documentFilePath (all four strategies), preserving Studio's content_path hardening. Document listing under non-file strategies is a documented follow-up (shared with brain-cache's walk).

3. Singleton/dictionary content never status-filtered

Only collection was filtered, so a draft singleton/dictionary published in full. These kinds store meta as a single object; they're now gated as a unit — a non-published unit skips both content and meta so the stale-object sweep GCs any prior copy.

Bonus: narrowed the swallow-everything try/catch

Content-file absence stays a silent skip, but a corrupt meta parse / upload error now surfaces via reportDataLossRisk instead of being swallowed into an unfiltered publish.

Tests

  • All four locale_strategy layouts × JSON + document, non-i18n collapse, content_path + strategy, path-traversal/protected rejection.
  • Default-locale meta path (reported env), draft singleton hidden, published singleton meta verbatim, legacy no-meta singleton, corrupt-meta surfacing, absent-content silent skip.
  • Full unit suite green (743 tests).

Verification note

Confirm on the content repo: meta/sponsors/tr.json says published and meta/sponsors/en.json does not exist → closes the diagnosis 100%.

… in builds

Three related correctness bugs in the CDN build path, all rooted in path/meta
resolution diverging from MCP's canonical contract:

- Non-i18n content/meta lives under the DEFAULT locale (that's where MCP
  writes it), which is not necessarily `supported[0]`. The builder resolved the
  meta path via `locales[0]`, so a project whose default differs from
  supported[0] (e.g. default=tr, supported=[en,tr]) read a non-existent meta
  file — the status filter went blind (drafts leaked, meta output empty). Now
  uses `config.locales.default`, mirroring brain-cache. Fixed for collections,
  singletons/dictionaries, and non-i18n documents.

- `resolveContentPath` ignored `model.locale_strategy`, only resolving the
  default `file` layout. `suffix`/`directory`/`none` i18n models read the wrong
  path → silent skip in the CDN build and brain cache. Realigned byte-for-byte
  with MCP's `contentFilePath`/`documentFilePath` (all four strategies), keeping
  Studio's content_path hardening. Document *listing* under non-file strategies
  remains a documented follow-up.

- Singleton/dictionary content was never status-filtered (only collections
  were), so a draft singleton/dictionary published in full. These kinds store
  meta as a single object; they're now gated as a unit — a non-published unit
  skips both content and meta so the stale-object sweep GCs any prior copy.

Also narrows the per-model build try/catch: content-file absence stays a silent
skip, but a corrupt meta parse / upload error now surfaces via reportDataLossRisk
instead of being swallowed into an unfiltered publish.

Adds regression coverage for all four locale_strategy layouts, the default-locale
meta path, singleton/dictionary status gating, and error surfacing.
@ABB65 ABB65 marked this pull request as draft July 15, 2026 16:58
@ABB65 ABB65 marked this pull request as ready for review July 15, 2026 16:59
@ABB65 ABB65 merged commit aa87956 into main Jul 15, 2026
2 checks passed
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