fix(cdn): honor default locale, locale_strategy, and singleton status in builds#152
Merged
Merged
Conversation
… 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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
A connected project reported published non-i18n content (
sponsors) serving200 {}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 localeNon-i18n content/meta lives under the default locale (where MCP writes it), which is not necessarily
supported[0]. The builder usedlocales[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 usesconfig.locales.default, mirroringbrain-cache.ts. Fixed for collections, singletons/dictionaries, and non-i18n documents.2.
resolveContentPathignoredlocale_strategyIt only resolved the default
filelayout.suffix/directory/nonei18n models read the wrong path → silent skip in the CDN build and brain cache. Realigned byte-for-byte with MCP'scontentFilePath/documentFilePath(all four strategies), preserving Studio'scontent_pathhardening. 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
collectionwas 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
reportDataLossRiskinstead of being swallowed into an unfiltered publish.Tests
locale_strategylayouts × JSON + document, non-i18n collapse,content_path+ strategy, path-traversal/protected rejection.Verification note
Confirm on the content repo:
meta/sponsors/tr.jsonsayspublishedandmeta/sponsors/en.jsondoes not exist → closes the diagnosis 100%.